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五种设计模式小结
Mar 23 PHP
PHP写的获取各搜索蜘蛛爬行记录代码
Aug 21 PHP
PHP jQuery表单,带验证具体实现方法
Feb 15 PHP
PHP中使用memcache存储session的三种配置方法
Apr 05 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十三)
Jun 26 PHP
ThinkPHP模板判断输出Present标签用法详解
Jun 30 PHP
php中把美国时间转为北京时间的自定义函数分享
Jul 28 PHP
PHP中Fatal error session_start()错误解决步骤
Aug 05 PHP
PHP 常用时间函数资料整理
Oct 22 PHP
PHP 进度条函数的简单实例
Sep 19 PHP
PHP实现的简单组词算法示例
Apr 10 PHP
PHP使用PDO操作sqlite数据库应用案例
Mar 07 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编程函数安全篇
2013/01/08 PHP
php利用新浪接口查询ip获取地理位置示例
2014/01/20 PHP
适用于抽奖程序、随机广告的PHP概率算法实例
2014/04/09 PHP
php中addslashes函数与sql防注入
2014/11/17 PHP
Windows下PHP开发环境搭建教程(Apache+PHP+MySQL)
2016/06/13 PHP
php求数组全排列,元素所有组合的方法总结
2017/03/14 PHP
基于mootools 1.3框架下的图片滑动效果代码
2011/04/22 Javascript
YUI模块开发原理详解
2013/11/18 Javascript
javascript折半查找详解
2015/01/26 Javascript
Jsonp 关键字详解及json和jsonp的区别,ajax和jsonp的区别
2015/12/30 Javascript
jQuery实现简单的网页换肤效果示例
2016/09/18 Javascript
深入理解Angularjs向指令传递数据双向绑定机制
2016/12/31 Javascript
nodejs使用express创建一个简单web应用
2017/03/31 NodeJs
如何选择jQuery版本 1.x? 2.x? 3.x?
2017/04/01 jQuery
ES6新增的math,Number方法
2017/08/06 Javascript
vue轮播图插件vue-awesome-swiper
2017/11/27 Javascript
jQuery选择器之基本选择器用法实例分析
2019/02/19 jQuery
nodejs实现日志读取、日志查找及日志刷新的方法分析
2019/05/20 NodeJs
jquery实现购物车基本功能
2019/10/25 jQuery
全面解析js中的原型,原型对象,原型链
2021/01/25 Javascript
使用Python将数组的元素导出到变量中(unpacking)
2016/10/27 Python
Python基于回溯法子集树模板解决旅行商问题(TSP)实例
2017/09/05 Python
django使用admin站点上传图片的实例
2019/07/28 Python
python批量图片处理简单示例
2019/08/06 Python
CSS+jQuery+PHP+MySQL实现的在线答题功能
2015/04/25 HTML / CSS
天巡全球:Skyscanner Global
2017/06/20 全球购物
澳大利亚新奇小玩意网站:Yellow Octopus
2017/12/28 全球购物
Nº21官方在线商店:numeroventuno.com
2019/09/26 全球购物
.NET remoting中对象激活的两种方式
2015/06/08 面试题
小学语文国培感言
2014/03/04 职场文书
3.15国际消费者权益日主题活动活动总结
2014/03/16 职场文书
请假条格式范文
2014/04/10 职场文书
校园绿化美化方案
2014/06/08 职场文书
专题组织生活会方案
2014/06/15 职场文书
工作汇报开头与结尾怎么写
2014/11/08 职场文书
Python使用socket去实现TCP客户端和TCP服务端
2022/04/12 Python