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 相关文章推荐
example2.php
Oct 09 PHP
PHP&amp;MYSQL服务器配置说明
Oct 09 PHP
自己动手做一个SQL解释器
Oct 09 PHP
一个程序下载的管理程序(二)
Oct 09 PHP
用PHP生成html分页列表的代码
Mar 18 PHP
几种有用的变型 PHP中循环语句的用法介绍
Jan 30 PHP
解析php中如何调用用户自定义函数
Aug 06 PHP
Yii 快速,安全,专业的PHP框架
Sep 03 PHP
php中的观察者模式简单实例
Jan 20 PHP
PHP实现阳历到农历转换的类实例
Mar 07 PHP
支付宝服务窗API接口开发php版本
Jul 20 PHP
laravel Model 执行事务的实现
Oct 10 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执行linux系统命令的常用函数使用说明
2010/04/27 PHP
回帖脱衣服的图片实现代码
2014/02/15 PHP
使用phpexcel类实现excel导入mysql数据库功能(实例代码)
2016/05/12 PHP
限制文本字节数js代码
2007/03/06 Javascript
Jquery 常用方法经典总结
2010/01/28 Javascript
Javascript 面向对象编程(coolshell)
2012/03/18 Javascript
JavaScript prototype属性深入介绍
2012/11/27 Javascript
js原型继承的两种方法对比介绍
2014/03/30 Javascript
基于jquery的手风琴图片展示效果实现方法
2014/12/16 Javascript
javascript中Array数组的迭代方法实例分析
2015/02/04 Javascript
js调用webservice构造SOAP进行身份验证
2016/04/27 Javascript
深入理解JavaScript中的并行处理
2016/09/22 Javascript
echarts同一页面中四个图表切换的js数据交互方法示例
2018/07/03 Javascript
jQuery实现监听下拉框选中内容发生改变操作示例
2018/07/13 jQuery
vue-router中的hash和history两种模式的区别
2018/07/17 Javascript
element-ui 中的table的列隐藏问题解决
2018/08/24 Javascript
Nodejs实现的操作MongoDB数据库功能完整示例
2019/02/02 NodeJs
解决vue跨域axios异步通信问题
2019/04/17 Javascript
微信小程序代码上传、审核发布小程序
2019/05/18 Javascript
Openlayers绘制聚合标注
2020/09/28 Javascript
解决新建一个vue项目过程中遇到的问题
2020/10/22 Javascript
js实现弹幕墙效果
2020/12/10 Javascript
使用python实现strcmp函数功能示例
2014/03/25 Python
python简单实现计算过期时间的方法
2015/06/09 Python
对python多线程SSH登录并发脚本详解
2019/02/14 Python
Python Opencv任意形状目标检测并绘制框图
2019/07/23 Python
python切割图片的示例
2020/11/12 Python
营销人才自我鉴定范文
2013/12/25 职场文书
医院护士的求职信
2014/01/03 职场文书
妇女儿童发展规划实施方案
2014/03/16 职场文书
幼儿园教师岗位职责
2014/03/17 职场文书
班组建设经验交流材料
2014/05/12 职场文书
师德师风事迹材料
2014/12/20 职场文书
格林童话读书笔记
2015/06/30 职场文书
SQLServer中JSON文档型数据的查询问题解决
2021/06/27 SQL Server
Java基于Dijkstra算法实现校园导游程序
2022/03/17 Java/Android