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 CKEditor 上传图片实现代码
Nov 06 PHP
php网上商城购物车设计代码分享
Feb 15 PHP
php 对输入信息的进行安全过滤的函数代码
Jun 29 PHP
基于php伪静态的实现详细介绍
Apr 28 PHP
PHP轻量级数据库操作类Medoo增加、删除、修改、查询例子
Jul 04 PHP
PHP判断手机是IOS还是Android
Dec 09 PHP
thinkPHP中钩子的两种配置调用方法详解
Nov 11 PHP
ThinkPHP模板标签eq if 中区分0,null,false的方法
Mar 24 PHP
php面向对象之反射功能与用法分析
Mar 29 PHP
Laravel 5使用Laravel Excel实现Excel/CSV文件导入导出的功能详解
Oct 11 PHP
php使用lua+redis实现限流,计数器模式,令牌桶模式
Apr 04 PHP
laravel-admin select框默认选中的方法
Oct 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
日本十大科幻动漫 宇宙骑士垫底,第一已成经典
2020/03/04 日漫
PHP 自定义错误处理函数trigger_error()
2013/03/26 PHP
PHP面向对象程序设计之类常量用法实例
2014/08/20 PHP
基于jquery 的一个progressbar widge
2010/10/29 Javascript
JavaScript 继承使用分析
2011/05/12 Javascript
javascript实现div的显示和隐藏的小例子
2013/06/25 Javascript
javascript实现字符串反转的方法
2015/02/05 Javascript
JavaScript中的small()方法使用详解
2015/06/08 Javascript
利用Node.js制作爬取大众点评的爬虫
2016/09/22 Javascript
JS编写函数实现对身份证号码最后一位的验证功能
2016/12/29 Javascript
jQuery插件HighCharts实现的2D堆条状图效果示例【附demo源码下载】
2017/03/14 Javascript
基于Bootstrap分页的实例讲解(必看篇)
2017/07/04 Javascript
jQuery 中msgTips 顶部弹窗效果实现代码
2017/08/14 jQuery
jQuery Datatable 多个查询条件自定义提交事件(推荐)
2017/08/24 jQuery
vue+webpack 打包文件 404 页面空白的解决方法
2018/02/28 Javascript
原生js实现二级联动菜单
2019/11/27 Javascript
vue中的循环对象属性和属性值用法
2020/09/04 Javascript
原生js实现移动小球(碰撞检测)
2020/12/17 Javascript
python奇偶行分开存储实现代码
2018/03/19 Python
python ipset管理 增删白名单的方法
2019/01/14 Python
Python通过TensorFlow卷积神经网络实现猫狗识别
2019/03/14 Python
PyCharm+Qt Designer+PyUIC安装配置教程详解
2019/06/13 Python
Django如何实现网站注册用户邮箱验证功能
2019/08/14 Python
为您的家、后院、车库等在线购物:Spreetail
2019/06/17 全球购物
String是最基本的数据类型吗?
2013/06/13 面试题
毕业生求职简历的自我评价
2013/10/23 职场文书
运动会广播稿80字
2014/01/23 职场文书
数控专业毕业生自荐信范文
2014/03/04 职场文书
信息工作经验交流材料
2014/05/28 职场文书
世博会口号
2014/06/20 职场文书
2014年教研室工作总结
2014/12/06 职场文书
自我检讨报告
2015/01/28 职场文书
社区六一儿童节活动总结
2015/02/11 职场文书
专项资金申请报告
2015/05/15 职场文书
关于运动会的宣传稿
2015/07/23 职场文书
通知怎么写?
2019/04/17 职场文书