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 相关文章推荐
域名查询代码公布
Oct 09 PHP
一个程序下载的管理程序(三)
Oct 09 PHP
让PHP支持页面回退的两种方法
Jan 10 PHP
PHP Google的translate API代码
Dec 10 PHP
php中可能用来加密字符串的函数[base64_encode、urlencode、sha1]
Jan 16 PHP
php 判断数组是几维数组
Mar 20 PHP
PHP的Yii框架中YiiBase入口类的扩展写法示例
Mar 17 PHP
php处理单文件、多文件上传代码分享
Aug 24 PHP
php rmdir使用递归函数删除非空目录实例详解
Oct 20 PHP
PHP递归遍历指定文件夹内的文件实现方法
Nov 15 PHP
Yii 访问 Gii(脚手架)时出现 403 错误
Jun 06 PHP
PHP 实现缩略图
Mar 09 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
2020显卡排行榜天梯图 显卡天梯图2020年3月最新版
2020/04/02 数码科技
php 在线打包_支持子目录
2008/06/28 PHP
php 格式化数字的时候注意数字的范围
2010/04/13 PHP
Destoon旺旺无法正常显示,点击提示“会员名不存在”的解决办法
2014/06/21 PHP
php中解析带中文字符的url函数分享
2015/01/20 PHP
php mysql PDO 查询操作的实例详解
2017/09/23 PHP
CI框架网页缓存简单用法分析
2018/12/26 PHP
JS实现网站菜单拖拽移位效果的方法
2015/09/24 Javascript
JS简单设置下拉选择框默认值的方法
2016/08/20 Javascript
ThinkJS中如何使用MongoDB的CURD操作
2016/12/13 Javascript
mui上拉加载功能实例详解
2017/04/13 Javascript
基于JavaScript实现表格滚动分页
2017/11/22 Javascript
微信小程序 功能函数小结(手机号验证*、密码验证*、获取验证码*)
2017/12/08 Javascript
layui监听select变化,以及设置radio选中的方法
2019/09/24 Javascript
jQuery 常用特效实例小结【显示与隐藏、淡入淡出、滑动、动画等】
2020/05/19 jQuery
jQuery+css实现的点击图片放大缩小预览功能示例【图片预览 查看大图】
2020/05/29 jQuery
Python使用minidom读写xml的方法
2015/06/03 Python
python基础教程之分支、循环简单用法
2016/06/16 Python
python numpy元素的区间查找方法
2018/11/14 Python
PyQt5 多窗口连接实例
2019/06/19 Python
Python 获取指定文件夹下的目录和文件的实现
2019/08/30 Python
Python 爬取必应壁纸的实例讲解
2020/02/24 Python
python数据库操作mysql:pymysql、sqlalchemy常见用法详解
2020/03/30 Python
美国知名的在线旅游服务网站:Priceline
2016/07/23 全球购物
英国电动工具购买网站:Anglia Tool Centre
2017/04/25 全球购物
高档奢华时装在线目的地:FORWARD by elyse walker
2017/10/16 全球购物
Bose加拿大官方网站:美国知名音响品牌
2019/03/21 全球购物
意大利单身交友网站:Meetic
2020/07/12 全球购物
自荐书封面下载
2013/11/29 职场文书
中学运动会广播稿
2014/01/19 职场文书
端午节活动策划方案
2014/03/09 职场文书
学校花圃的标语
2014/06/18 职场文书
2014年精神文明工作总结
2014/12/23 职场文书
详解Python生成器和基于生成器的协程
2021/06/03 Python
python ConfigParser库的使用及遇到的坑
2022/02/12 Python