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 18 PHP
codeigniter框架The URI you submitted has disallowed characters错误解决方法
May 06 PHP
php模拟用户自动在qq空间发表文章的方法
Jan 07 PHP
PHP中捕获超时事件的方法实例
Feb 12 PHP
php从csv文件读取数据并输出到网页的方法
Mar 14 PHP
php解析xml方法实例详解
May 12 PHP
PHP基于工厂模式实现的计算器实例
Jul 16 PHP
PHP针对字符串开头和结尾的判断方法
Jul 11 PHP
PHP获取当前日期及本周一是几月几号的方法
Mar 28 PHP
php中file_get_contents()函数用法实例
Feb 21 PHP
详解PHP多个进程配合redis的有序集合实现大文件去重
Mar 06 PHP
PHP实现百度人脸识别
May 06 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
递归列出所有文件和目录
2006/10/09 PHP
关于php fread()使用技巧
2010/01/22 PHP
PHP中几个常用的魔术常量
2012/02/23 PHP
addRule在firefox下的兼容写法
2006/11/30 Javascript
JavaScript实现禁止后退的方法
2006/12/27 Javascript
浅说js变量
2011/05/25 Javascript
js 时间格式与时间戳的相互转换示例代码
2013/12/25 Javascript
基于socket.io和node.js搭建即时通信系统
2014/07/30 Javascript
JS动态显示表格上下frame的方法
2015/03/31 Javascript
Bootstrap如何创建表单
2016/10/21 Javascript
bootstrap基础知识学习笔记
2016/11/02 Javascript
js中常用的Math方法总结
2017/01/12 Javascript
Bootstrap table右键功能实现方法
2017/02/20 Javascript
React-intl 实现多语言的示例代码
2017/11/03 Javascript
vue学习教程之带你一步步详细解析vue-cli
2017/12/26 Javascript
Angular实现的日程表功能【可添加及隐藏显示内容】
2017/12/27 Javascript
Node.js readline模块与util模块的使用
2018/03/01 Javascript
JavaScript设计模式之构造函数模式实例教程
2018/07/02 Javascript
详解微信小程序实现仿微信聊天界面(各种细节处理)
2019/02/17 Javascript
jQuery使用$.extend(true,object1, object2);实现深拷贝对象的方法分析
2019/03/06 jQuery
在微信小程序中使用图表的方法示例
2019/04/25 Javascript
解决vue项目运行提示Warnings while compiling.警告的问题
2020/09/18 Javascript
python编写网页爬虫脚本并实现APScheduler调度
2014/07/28 Python
python+selenium实现简历自动刷新的示例代码
2019/05/20 Python
django admin 添加自定义链接方式
2020/03/11 Python
HTML5 Web Workers之网站也能多线程的实现
2013/04/24 HTML / CSS
HTML5 Canvas绘制圆点虚线实例
2015/01/01 HTML / CSS
Urban Outfitters美国官网:美国生活方式品牌
2016/08/26 全球购物
美国汽车性能部件和赛车零件网站:Vivid Racing
2018/03/27 全球购物
俄罗斯香水在线商店:AromaCode
2019/12/04 全球购物
C语言面试题
2013/05/19 面试题
什么是Smart Navigation?
2016/07/03 面试题
XMLHttpRequest对象在IE和Firefox中创建方式有没有不同
2016/03/23 面试题
国旗下的演讲稿
2014/05/08 职场文书
县政府领导班子四风问题对照检查材料思想汇报
2014/09/26 职场文书
故宫英文导游词
2015/01/31 职场文书