php使用fputcsv实现大数据的导出操作详解


Posted in PHP onFebruary 27, 2020

本文实例讲述了php使用fputcsv实现大数据的导出操作。分享给大家供大家参考,具体如下:

为了实验大数据的导出,我们这里先自已创建一张大表,表结构如下:

CREATE TABLE `tb_users` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',
 `name` varchar(32) DEFAULT '' COMMENT '用户名',
 `age` tinyint(3) DEFAULT '0' COMMENT '用户年龄',
 `desc` varchar(255) DEFAULT '' COMMENT '用户描述',
 `phone` varchar(11) DEFAULT '' COMMENT '用户手机',
 `qq` varchar(16) DEFAULT '' COMMENT '用户QQ',
 `email` varchar(64) DEFAULT '' COMMENT '用户邮箱',
 `addr` varchar(255) DEFAULT '' COMMENT '用户地址',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 然后写个php脚本往这个表插入数据,代码如下:

<?php
set_time_limit(0);
ini_set('memory_limit', '128M');

//使用TP3.2的String类,php7下会报错,注意把类名换一下
require './String.class.php';
use Org\Util\NewString;

$begin = microtime(true);

$db = new mysqli('127.0.0.1', 'root', '', 'test');

if($db->connect_error) {
  die('connect error');
}
//数据插入语句
$insSql = '';

//一百万数据,分200步,每步插入5000条
$step = 200;
$nums = 5000;

for($s = 0; $s < $step; ++$s) {
  $insSql = 'INSERT INTO tb_users VALUES';
  for($n = 0; $n < $nums; ++$n) {
    $name = NewString::randString(3, 4);
    $age = mt_rand(1, 120);
    $desc = NewString::randString(64, 4);
    $phone = NewString::randString(11, 1);
    $qq = NewString::randString(13, 1);
    $email = $qq . '@qq.com';
    $addr = NewString::randString(128, 4);
    $insSql .= "(NULL, '{$name}', $age, '{$desc}', '{$phone}', '{$qq}', '{$email}', '{$addr}'),";
  }
  $insSql = rtrim($insSql, ',');
  $db->query($insSql);
}
$end = microtime(true);
echo '用时:', $end - $begin;

$db->close();

里面用到的TP3.2的String类大家自行上TP官网下载。整个用时2个多小时,最后数据大小662M。

现在我们用php提供的fputcsv来导出这一百万的数据,原理就是打开一个标准输出流,然后把数据按一万条来分割,每一万条就刷新缓冲区。

<?php
set_time_limit(0);
ini_set('memory_limit', '128M');

$fileName = date('YmdHis', time());
header('Content-Type: application/vnd.ms-execl');
header('Content-Disposition: attachment;filename="' . $fileName . '.csv"');

$begin = microtime(true);

//打开php标准输出流
//以写入追加的方式打开
$fp = fopen('php://output', 'a');

$db = new mysqli('127.0.0.1', 'root', '', 'test');

if($db->connect_error) {
  die('connect error');
}

//我们试着用fputcsv从数据库中导出1百万的数据
//我们每次取1万条数据,分100步来执行
//如果线上环境无法支持一次性读取1万条数据,可把$nums调小,$step相应增大。
$step = 100;
$nums = 10000;

//设置标题
$title = array('ID', '用户名', '用户年龄', '用户描述', '用户手机', '用户QQ', '用户邮箱', '用户地址');
foreach($title as $key => $item) {
  $title[$key] = iconv('UTF-8', 'GBK', $item);
}
//将标题写到标准输出中
fputcsv($fp, $title);

for($s = 1; $s <= $step; ++$s) {
  $start = ($s - 1) * $nums;
  $result = $db->query("SELECT * FROM tb_users ORDER BY id LIMIT {$start},{$nums}");
  
  if($result) {
    while($row = $result->fetch_assoc()) {
      foreach($row as $key => $item) {
        //这里必须转码,不然会乱码
        $row[$key] = iconv('UTF-8', 'GBK', $item);
      }
      fputcsv($fp, $row);
    }
    $result->free();
    
    //每1万条数据就刷新缓冲区
    ob_flush();
    flush();
  }
}

$end = microtime(true);
echo '用时:', $end - $begin;

整个过程用时5分钟,最终生成的csv文件大小420M。

php使用fputcsv实现大数据的导出操作详解

php使用fputcsv实现大数据的导出操作详解

php使用fputcsv实现大数据的导出操作详解

对于如何用phpexcel导出大数据,并没有什么比较好的方案,phpexcel提供的一些缓存方法,数据压缩,虽然内存使用小了,但所用时间则加长了,时间换空间,显然并不是最好的方案。比较靠谱的方法还是生成多个下载链接地址,把你要下载的数据,以get形式传递当前页数,后台进行数据分页然后导出。

<a href="/downSearchData.php?参数1=值1&参数2=值2&page=1" rel="external nofollow" >下载汇总结果1</a>
<a href="/downSearchData.php?参数1=值1&参数2=值2&page=2" rel="external nofollow" >下载汇总结果2</a>
<a href="/downSearchData.php?参数1=值1&参数2=值2&page=3" rel="external nofollow" >下载汇总结果3</a>

 比如你有一个查询数据表单,ID为searchFrm,然后你想把导出数据按1万条分割(phpexcel一次导出1万条是没有问题的,效率还行)

<form id="searchFrm">
  姓名<input type="text" name="uname">
  <input type="button" id="searchDataBtn" value="导出汇总结果">
</form>
<div id="searchDataList"></div>

<script type="script">
  $("#searchDataBtn").on("click", function() {
    var params = $("#searchFrm").serialize();
    
    //获取查询数据的条数
    $.get("/getSearchDataRows?" + params, function(data) {
      var downDataList = "";
      if(data["rows"]) {
        //rows是数据总条数,pageSize是一页多少条
        var pageNum = Math.ceil(data["rows"] / data["pageSize"]);
        for(var i = 1; i <= pageNum; ++i) {
          downDataList += "<a href='/downSearchData.php?'" + params + "&page=" + i + ">下载汇总结果" + i + "</a>  ";
        }
        $("#searchDataList").html(downDataList);
      } else {
        $("#searchDataList").text("没有数据");
      }
    }, "json");
    return false;
  });
</script>

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP类的使用 实例代码讲解
Dec 28 PHP
Pain 全世界最小最简单的PHP模板引擎 (普通版)
Oct 23 PHP
ThinkPHP关联模型操作实例分析
Sep 23 PHP
php中检查文件或目录是否存在的代码小结
Oct 22 PHP
成为好程序员必须避免的5个坏习惯
Jul 04 PHP
Smarty中常用变量操作符汇总
Oct 27 PHP
codeigniter中view通过循环显示数组数据的方法
Mar 20 PHP
php实现RSA加密类实例
Mar 26 PHP
PHP实现的蚂蚁爬杆路径算法代码
Dec 03 PHP
php json相关函数用法示例
Mar 28 PHP
PHP数组去重的更快实现方式分析
May 09 PHP
php中钩子(hook)的原理与简单应用demo示例
Sep 03 PHP
gearman中任务的优先级和返回状态实例分析
Feb 27 #PHP
gearman中worker常驻后台,导致MySQL server has gone away的解决方法
Feb 27 #PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
Feb 27 #PHP
gearman管理工具GearmanManager的安装与php使用方法示例
Feb 27 #PHP
php使用gearman进行任务分发操作实例详解
Feb 26 #PHP
php实现根据身份证获取精准年龄
Feb 26 #PHP
ThinkPHP5与单元测试PHPUnit使用详解
Feb 23 #PHP
You might like
PHP冒泡排序算法代码详细解读
2011/07/17 PHP
PHP提示Notice: Undefined variable的解决办法
2012/11/24 PHP
thinkphp缓存技术详解
2014/12/09 PHP
[原创]php实现子字符串位置相互对调互换的方法
2016/06/02 PHP
Yii2 rbac权限控制之rule教程详解
2016/06/23 PHP
mac系统下安装多个php并自由切换的方法详解
2017/04/21 PHP
一个很酷的拖动层的js类,兼容IE及Firefox
2009/06/23 Javascript
JS鼠标事件大全 推荐收藏
2011/11/01 Javascript
JavaScript中的方法重载实例
2015/03/16 Javascript
angular和BootStrap3实现购物车功能
2017/01/25 Javascript
浅谈 Vue v-model指令的实现原理
2017/06/08 Javascript
JS获取当前时间的年月日时分秒及时间的格式化的方法
2019/12/18 Javascript
JS如何实现封装列表右滑动删除收藏按钮
2020/07/23 Javascript
JavaScript点击按钮生成4位随机验证码
2021/01/28 Javascript
[02:51]DOTA2战队出征照拍摄花絮 TI3明星化身时尚男模
2013/07/22 DOTA
跟老齐学Python之print详解
2014/09/28 Python
python中string模块各属性以及函数的用法介绍
2016/05/30 Python
Python+matplotlib绘制不同大小和颜色散点图实例
2018/01/19 Python
django 发送手机验证码的示例代码
2018/04/25 Python
对numpy中二进制格式的数据存储与读取方法详解
2018/11/01 Python
python给微信好友定时推送消息的示例
2019/02/20 Python
python二维码操作:对QRCode和MyQR入门详解
2019/06/24 Python
python 实现按对象传值
2019/12/26 Python
新建文件时Pycharm中自动设置头部模板信息的方法
2020/04/17 Python
几款好用的python工具库(小结)
2020/10/20 Python
canvas线条的属性详解
2018/03/27 HTML / CSS
大学生大二自我鉴定
2013/10/28 职场文书
综合实践活动方案
2014/02/14 职场文书
高中军训第一天感言
2014/03/06 职场文书
《画风》教学反思
2014/04/16 职场文书
法律专业自荐信
2014/06/03 职场文书
2015年工程部工作总结
2015/04/30 职场文书
幼儿园大班教师随笔
2015/08/14 职场文书
个人职业生涯规划之自我评估篇
2019/09/03 职场文书
Nginx tp3.2.3 404问题解决方案
2021/03/31 Servers
Python竟然能剪辑视频
2021/05/25 Python