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 at(@)符号的用法简介
Jul 11 PHP
PHP 时间日期操作实战
Aug 26 PHP
探讨php中header的用法详解
Jun 07 PHP
PHP 二维数组根据某个字段排序的具体实现
Jun 03 PHP
ThinkPHP之R方法实例详解
Jun 20 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(一)
Jun 23 PHP
CodeIgniter框架验证码类库文件与用法示例
Mar 18 PHP
一个实用的php验证码类
Jul 06 PHP
Linux下源码包安装Swoole及基本使用操作图文详解
Apr 02 PHP
php多进程中的阻塞与非阻塞操作实例分析
Mar 04 PHP
如何在Laravel之外使用illuminate组件详解
Sep 20 PHP
YII2 全局异常处理深入讲解
Mar 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
php 目录遍历、删除 函数的使用介绍
2013/04/28 PHP
php缩放图片(根据宽高的等比例缩放)实例介绍
2013/06/09 PHP
PHP中变量引用与变量销毁机制分析
2014/11/15 PHP
thinkPHP3.1验证码的简单实现方法
2016/04/22 PHP
js检测客户端不是firefox则提示下载
2007/04/07 Javascript
JAVASCRIPT style 中visibility和display之间的区别
2010/01/22 Javascript
判断是否安装flash player及当前版本的JS代码
2013/08/08 Javascript
浅谈jQuery中对象遍历.eq().first().last().slice()方法
2014/11/26 Javascript
jQuery功能函数详解
2015/02/01 Javascript
H5用户注册表单页 注册模态框!
2016/09/17 Javascript
AngularJS 在同一个界面启动多个ng-app应用模块详解
2016/12/20 Javascript
jQuery中的deferred对象和extend方法详解
2017/05/08 jQuery
ES6使用Set数据结构实现数组的交集、并集、差集功能示例
2017/10/31 Javascript
vue-cli 2.*中导入公共less文件的方法步骤
2018/11/22 Javascript
js中Array对象的常用遍历方法详解
2019/01/17 Javascript
Django+vue跨域问题解决的详细步骤
2019/01/20 Javascript
解决layui富文本编辑器图片上传无法回显的问题
2019/09/18 Javascript
浅谈Layui的eleTree树式选择器使用方法
2019/09/25 Javascript
vue实现路由懒加载的3种方法示例
2020/09/01 Javascript
[01:00] DOTA2英雄背景故事第五期之重力引力法则谜团
2020/07/16 DOTA
python查询sqlite数据表的方法
2015/05/08 Python
python引入导入自定义模块和外部文件的实例
2017/07/24 Python
python3.5 email实现发送邮件功能
2018/05/22 Python
解决python3 Pycharm上连接数据库时报错的问题
2018/12/03 Python
Python通过paramiko远程下载Linux服务器上的文件实例
2018/12/27 Python
python 画3维轨迹图并进行比较的实例
2019/12/06 Python
使用 Python 读取电子表格中的数据实例详解
2020/04/17 Python
python 批量下载bilibili视频的gui程序
2020/11/20 Python
H5调用相机拍照并压缩图片的实例代码
2017/07/20 HTML / CSS
Skyscanner台湾:全球知名的旅行比价引擎
2018/07/01 全球购物
美国葡萄酒网上商店:Martha Stewart Wine Co.
2019/03/17 全球购物
2014年酒店前台工作总结
2014/11/14 职场文书
小学生教师节广播稿
2015/08/19 职场文书
如何利用js在两个html窗口间通信
2021/04/27 Javascript
深入理解go缓存库freecache的使用
2022/02/15 Golang
Apache Linkis 中间件架构及快速安装步骤
2022/03/16 Servers