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实现验证码功能
Oct 09 PHP
由php if 想到的些问题
Mar 22 PHP
php 8小时时间差的解决方法小结
Dec 22 PHP
基于PHP选项与信息函数的使用详解
May 10 PHP
解析php DOMElement 操作xml 文档的实现代码
May 10 PHP
PHP FTP操作类代码( 上传、拷贝、移动、删除文件/创建目录)
May 10 PHP
如何让thinkphp在模型中自动完成session赋值小教程
Sep 05 PHP
php脚本运行时的超时机制详解
Feb 17 PHP
php使用pear_smtp发送邮件
Apr 15 PHP
Yii2增删改查之查询 where参数详细介绍
Aug 08 PHP
PHPExcel实现表格导出功能示例【带有多个工作sheet】
Jun 13 PHP
Laravel5.7 数据库操作迁移的实现方法
Apr 12 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将字符串转换成16进制的方法
2015/03/17 PHP
JavaScript实现Sleep函数的代码
2007/03/04 Javascript
js去字符串前后空格5种实现方法及比较
2013/04/03 Javascript
Javascript堆排序算法详解
2014/12/03 Javascript
浅析JavaScript事件和方法
2015/02/28 Javascript
javascript显式类型转换实例分析
2015/04/25 Javascript
JS时间特效最常用的三款
2015/08/19 Javascript
angularjs学习笔记之双向数据绑定
2015/09/26 Javascript
jquery 表单验证之通过 class验证表单不为空
2015/11/02 Javascript
百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
2016/02/19 Javascript
jQuery实现div拖拽效果实例分析
2016/02/20 Javascript
JS及PHP代码编写八大排序算法
2016/07/12 Javascript
基于jQuery的表单填充实例
2017/08/22 jQuery
使用axios实现上传图片进度条功能
2017/12/21 Javascript
vue-cli 打包后提交到线上出现 &quot;Uncaught SyntaxError:Unexpected token&quot; 报错
2018/11/06 Javascript
微信小程序时间轴实现方法示例
2019/01/14 Javascript
9种方法优化jQuery代码详解
2020/02/04 jQuery
package.json各个属性说明详解
2020/03/11 Javascript
javaScript实现一个队列的方法
2020/07/14 Javascript
vue使用axios实现excel文件下载的功能
2020/07/16 Javascript
[01:21:58]守擂赛DOTA2第一周决赛
2020/04/22 DOTA
深入理解Javascript中的this关键字
2015/03/27 Python
讲解Python中的标识运算符
2015/05/14 Python
python 与GO中操作slice,list的方式实例代码
2017/03/20 Python
python实现简易通讯录修改版
2018/03/13 Python
Python中多个数组行合并及列合并的方法总结
2018/04/12 Python
python 利用pandas将arff文件转csv文件的方法
2019/02/12 Python
教你如何编写、保存与运行Python程序的方法
2019/07/12 Python
Django上使用数据可视化利器Bokeh解析
2019/07/31 Python
Python 跨.py文件调用自定义函数说明
2020/06/01 Python
获取CSDN文章内容并转换为markdown文本的python
2020/09/06 Python
详解使用双缓存解决Canvas clearRect引起的闪屏问题
2019/04/29 HTML / CSS
SkinCeuticals官网:美国药妆品牌
2018/04/19 全球购物
活动策划邀请函
2014/02/06 职场文书
党的群众路线专项整治方案
2014/11/03 职场文书
Nginx四层负载均衡的配置指南
2021/06/11 Servers