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 相关文章推荐
php5 pdo新改动加载注意事项
Sep 11 PHP
不用mod_rewrite直接用php实现伪静态化页面代码
Oct 04 PHP
php二维数组用键名分组相加实例函数
Nov 06 PHP
浅析echo(),print(),print_r(),return之间的区别
Nov 27 PHP
PHP整数取余返回负数的相关解决方法
May 15 PHP
php实现专业获取网站SEO信息类实例
Apr 02 PHP
PHP实现批量重命名某个文件夹下所有文件的方法
Sep 04 PHP
PHP实现模拟http请求的方法分析
Dec 20 PHP
PHP fprintf()函数用法讲解
Feb 16 PHP
php抽象方法和普通方法的区别点总结
Oct 13 PHP
TP5框架实现签到功能的方法分析
Apr 05 PHP
Laravel框架源码解析之入口文件原理分析
May 14 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中time(),date(),mktime()区别介绍
2013/09/28 PHP
在php和MySql中计算时间差的方法详解
2015/03/27 PHP
Laravel 在views中加载公共页面的实现代码
2019/10/22 PHP
ASP SQL防注入的方法
2008/12/25 Javascript
javascript下判断一个元素是否存在的代码
2010/03/05 Javascript
将文本输入框内容加入表中的js代码
2013/08/18 Javascript
js实现俄罗斯方块小游戏分享
2014/01/31 Javascript
ListBox实现上移,下移,左移,右移的简单实例
2014/02/13 Javascript
js验证IP及子网掩码的合法性有效性示例
2014/04/30 Javascript
jQuery 插件开发指南
2014/11/14 Javascript
js使用DOM操作实现简单留言板的方法
2015/04/10 Javascript
Javascript编写2048小游戏
2015/07/07 Javascript
整理Javascript数组学习笔记
2015/11/29 Javascript
js仿百度音乐全选操作
2017/01/13 Javascript
微信小程序-获得用户输入内容
2017/02/13 Javascript
js中开关变量使用实例
2017/02/24 Javascript
完美实现js焦点轮播效果(二)(图片可滚动)
2017/03/07 Javascript
基于nodejs 的多页面爬虫实例代码
2017/05/31 NodeJs
详解JavaScript添加给定的标签选项
2018/09/17 Javascript
python中执行shell的两种方法总结
2017/01/10 Python
在python中利用GDAL对tif文件进行读写的方法
2018/11/29 Python
tensorflow如何批量读取图片
2019/08/29 Python
Python3实现配置文件差异对比脚本
2019/11/18 Python
Python高级property属性用法实例分析
2019/11/19 Python
python自定义函数def的应用详解
2020/06/03 Python
Python venv虚拟环境配置过程解析
2020/07/08 Python
详解scrapy内置中间件的顺序
2020/09/28 Python
python 匿名函数与三元运算学习笔记
2020/10/23 Python
世界上最大的街头服饰网站:Karmaloop
2017/02/04 全球购物
捐款倡议书
2014/04/14 职场文书
政治表现评语
2014/05/04 职场文书
学习计划书怎么写
2014/09/15 职场文书
关于成立领导小组的通知
2015/04/23 职场文书
2019年预备党员的思想汇报:加深对党的认知
2019/09/25 职场文书
详解CocosCreator消息分发机制
2021/04/16 Javascript
Python基础之pandas数据合并
2021/04/27 Python