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 相关文章推荐
用IE远程创建Mysql数据库的简易程序
Oct 09 PHP
同一空间绑定多个域名而实现访问不同页面的PHP代码
Dec 06 PHP
谈谈新手如何学习PHP
Dec 23 PHP
PHP模块 Memcached功能多于Memcache
Jun 14 PHP
PHP中怎样保持SESSION不过期 原理及方案介绍
Aug 08 PHP
php读取csv文件后,uft8 bom导致在页面上显示出现问题的解决方法
Aug 10 PHP
PHP类的反射用法实例
Nov 03 PHP
php通过记录IP来防止表单重复提交方法分析
Dec 16 PHP
[原创]php使用curl判断网页404(不存在)的方法
Jun 23 PHP
PHP中ajax无刷新上传图片与图片下载功能
Feb 21 PHP
PHP实现图片批量打包下载功能
Mar 01 PHP
详解PHP素材图片上传、下载功能
Apr 12 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基础知识:类与对象(3) 构造函数和析构函数
2006/12/13 PHP
php+mysqli实现将数据库中一张表信息打印到表格里的方法
2015/01/28 PHP
PHP中list方法用法示例
2016/12/01 PHP
解析PHP之提取多维数组指定列的方法
2017/01/03 PHP
弹出层之1:JQuery.Boxy (一) 使用介绍
2011/10/06 Javascript
JavaScript link方法入门实例(给字符串加上超链接)
2014/10/17 Javascript
JavaScript常用标签和方法总结
2015/09/01 Javascript
AngularJS中如何使用$parse或$eval在运行时对Scope变量赋值
2016/01/25 Javascript
Bootstrap树形控件使用方法详解
2016/01/27 Javascript
prototype.js常用函数详解
2016/06/18 Javascript
AngularJS模块详解及示例代码
2016/08/17 Javascript
老生常谈的跨域处理
2017/01/11 Javascript
微信小程序访问node.js接口服务器搭建教程
2017/04/25 Javascript
vue 运用mock数据的示例代码
2017/11/07 Javascript
p5.js入门教程和基本形状绘制
2018/03/15 Javascript
安装vue-cli的简易过程
2018/05/22 Javascript
微信小程序实现手指触摸画板
2018/07/09 Javascript
JS实现继承的几种常用方式示例
2019/06/22 Javascript
jQuery-Citys省市区三级菜单联动插件使用详解
2019/07/26 jQuery
vue-cli4使用全局less文件中的变量配置操作
2020/10/21 Javascript
从零学Python之入门(二)基本数据类型
2014/05/25 Python
python中列表元素连接方法join用法实例
2015/04/07 Python
Pyqt5 实现跳转界面并关闭当前界面的方法
2019/06/19 Python
使用Fabric自动化部署Django项目的实现
2019/09/27 Python
Django1.11自带分页器paginator的使用方法
2019/10/31 Python
Python读取VOC中的xml目标框实例
2020/03/10 Python
小结Python的反射机制
2020/09/28 Python
canvas学习笔记之2d画布基础的实现
2019/02/21 HTML / CSS
竞聘书模板
2014/03/31 职场文书
介绍信格式
2015/01/30 职场文书
盗窃罪辩护词范文
2015/05/21 职场文书
学会感恩主题班会
2015/08/12 职场文书
领导莅临指导欢迎词
2015/09/30 职场文书
2016秋季田径运动会广播稿
2015/12/21 职场文书
2016党员干部廉政准则学习心得体会
2016/01/20 职场文书
创业计划书之闲置物品置换中心
2019/12/25 职场文书