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仿ZOL分页类代码
Oct 02 PHP
PHP乱码问题,UTF-8乱码常见问题小结
Apr 09 PHP
ThinkPHP实现带验证码的文件上传功能实例
Nov 01 PHP
php获取四位字母和数字的随机数的实现方法
Jan 09 PHP
WordPres对前端页面调试时的两个PHP函数使用小技巧
Dec 22 PHP
php实现贪吃蛇小游戏
Jul 26 PHP
Yii2中事务的使用实例代码详解
Sep 07 PHP
PHP7.1方括号数组符号多值复制及指定键值赋值用法分析
Sep 26 PHP
php简单随机字符串生成方法示例
Apr 19 PHP
thinkphp5 加载静态资源路径与常量的方法
Dec 24 PHP
thinkPHP框架通过Redis实现增删改查操作的方法详解
May 13 PHP
Laravel中Kafka的使用详解
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 随机排序广告的实现代码
2011/05/09 PHP
2014过年倒计时示例
2014/01/31 PHP
PHP实现的简易版图片相似度比较
2015/01/07 PHP
PHP删除数组中指定值的元素常用方法实例分析【4种方法】
2018/08/21 PHP
javascript预览上传图片发现的问题的解决方法
2010/11/25 Javascript
js浮动图片的动态效果
2013/07/10 Javascript
js有序数组的连接问题
2013/10/01 Javascript
javascript实现多级联动下拉菜单的方法
2015/02/06 Javascript
JavaScript判断用户是否对表单进行了修改的方法
2015/03/18 Javascript
JS操作XML实例总结(加载与解析XML文件、字符串)
2015/12/08 Javascript
jquery插件uploadify多图上传功能实现代码
2016/08/12 Javascript
如何解决IONIC页面底部被遮住无法向上滚动问题
2016/09/06 Javascript
JS实现间歇滚动的运动效果实例
2016/12/22 Javascript
浅谈Vue的基本应用
2016/12/27 Javascript
解决Extjs下拉框不显示的问题
2017/06/21 Javascript
jQuery模仿ToDoList实现简单的待办事项列表
2019/12/30 jQuery
python中from module import * 的一个坑
2014/07/20 Python
python爬虫实战之爬取京东商城实例教程
2017/04/24 Python
python机器学习之随机森林(七)
2018/03/26 Python
python 监听salt job状态,并任务数据推送到redis中的方法
2019/01/14 Python
Python字符串逆序的实现方法【一题多解】
2019/02/18 Python
Python对ElasticSearch获取数据及操作
2019/04/24 Python
Pyinstaller 打包exe教程及问题解决
2019/08/16 Python
Python opencv相机标定实现原理及步骤详解
2020/04/09 Python
python基于Kivy写一个图形桌面时钟程序
2021/01/28 Python
Crocs美国官方网站:卡骆驰洞洞鞋
2017/08/04 全球购物
Monnier Freres中文官网:法国领先的奢侈品配饰在线零售商
2017/11/01 全球购物
美国全球旅游运营商:Pacific Holidays
2018/06/18 全球购物
意大利买卖二手奢侈品网站:LAMPOO
2020/06/03 全球购物
Web Service面试题:如何搭建Axis2的开发环境
2012/06/20 面试题
电子专业推荐信范文
2013/11/18 职场文书
建筑总经理岗位职责
2014/02/02 职场文书
出国英文推荐信
2014/05/10 职场文书
2015年人事科工作总结
2015/04/28 职场文书
python pygame入门教程
2021/06/01 Python
Nginx设置HTTPS的方法步骤 443证书配置方法
2022/03/21 Servers