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 相关文章推荐
在apache下限制每个虚拟主机的并发数!!!!
Oct 09 PHP
PHP中json_encode、json_decode与serialize、unserialize的性能测试分析
Jun 09 PHP
destoon实现首页显示供应、企业、资讯条数的方法
Jul 15 PHP
php模仿asp Application对象在线人数统计实现方法
Jan 04 PHP
php的sso单点登录实现方法
Jan 08 PHP
PHP两种快速排序算法实例
Feb 15 PHP
PHP设计模式之装饰者模式代码实例
May 11 PHP
smarty学习笔记之常见代码段用法总结
Mar 19 PHP
php实现压缩合并js的方法【附demo源码下载】
Sep 22 PHP
PHP中使用OpenSSL生成证书及加密解密
Feb 05 PHP
PHP addAttribute()函数讲解
Feb 03 PHP
使用Git实现Laravel项目的自动化部署
Nov 24 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
解决form中action属性后面?传递参数 获取不到的问题
2017/07/21 PHP
用js自动判断浏览器分辨率的代码
2007/01/28 Javascript
javascript的日期对象、数组对象、二维数组使用说明
2014/12/22 Javascript
javascript获取重复次数最多的字符
2015/07/08 Javascript
javascript实现下拉提示选择框
2015/12/29 Javascript
对象转换为原始值的实现方法
2016/06/06 Javascript
【经典源码收藏】基于jQuery的项目常见函数封装集合
2016/06/07 Javascript
JavaScript必知必会(七)js对象继承
2016/06/08 Javascript
自制微信公众号一键排版工具
2016/09/22 Javascript
运用js教你轻松制作html音乐播放器
2020/04/17 Javascript
js获取元素的标签名实现方法
2016/10/08 Javascript
使用JS读取XML文件的方法
2016/11/25 Javascript
详解jQuery中基本的动画方法
2016/12/14 Javascript
bootstrap——bootstrapTable实现隐藏列的示例
2017/01/14 Javascript
js 博客内容进度插件详解
2017/02/19 Javascript
Restify中接入Socket.io报Error:Can’t set headers的错误解决
2017/03/28 Javascript
angular实现图片懒加载实例代码
2017/06/08 Javascript
React如何将组件渲染到指定DOM节点详解
2017/09/08 Javascript
Javascript Dom元素获取和添加详解
2019/09/24 Javascript
JS实现导航栏楼层特效
2020/01/01 Javascript
JavaScript中的this/call/apply/bind的使用及区别
2020/03/06 Javascript
python获取文件后缀名及批量更新目录下文件后缀名的方法
2014/11/11 Python
Python标准库urllib2的一些使用细节总结
2015/03/16 Python
python函数局部变量用法实例分析
2015/08/04 Python
Python基于高斯消元法计算线性方程组示例
2018/01/17 Python
Python Multiprocessing多进程 使用tqdm显示进度条的实现
2019/08/13 Python
python 如何将数据写入本地txt文本文件的实现方法
2019/09/11 Python
使用pandas库对csv文件进行筛选保存
2020/05/25 Python
美国转售二手商品的电子商务平台:BLINQ
2018/12/13 全球购物
什么是WEB控件?使用WEB控件有哪些优势?
2012/01/21 面试题
《翻越远方的大山》教学反思
2014/04/13 职场文书
2014年最新个人对照检查材料范文
2014/09/25 职场文书
教师党员自我剖析材料
2014/09/29 职场文书
私人房屋买卖协议书
2014/10/04 职场文书
加强作风建设工作总结
2014/10/23 职场文书
MySQL表锁、行锁、排它锁及共享锁的使用详解
2022/04/02 MySQL