php使用fputcsv实现大数据的导出操作详解

本文实例讲述了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。

对于如何用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>&nbsp;&nbsp;";
        }
        $("#searchDataList").html(downDataList);
      } else {
        $("#searchDataList").text("没有数据");
      }
    }, "json");
    return false;
  });
</script>

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php+mysql数据库操作入门教程》、《php+redis数据库程序设计技巧总结》、《php面向对象程序设计入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

(0)

相关推荐

  • php+ajax实现带进度条的大数据排队导出思路以及源码

    废话不多说,先上效果图: 点击导出,实现 点击导出 统计完成之后 点击确定 下面来谈谈实现的思路: 前面导出操作简单,从第二个导出操作开始: 点击"确定"调用exportCsv函数 复制代码 代码如下: <a class="on" href="javascript:exportCsv();"><em>导出</em></a> exportCvs函数如下function exportCsv(){ //清

  • phpadmin如何导入导出大数据文件及php.ini参数修改

    最近遇到了数据库过大的时候用phpadmin导入的问题,新版本的phpadmin导入限定是8M,老版本的可能2M,我的数据库有几十兆这可怎么办呢? 首先如果你有独立服务器或vps的话可以找到 Apache 下的php.ini 这个文件来修改这个8M或2M的限制,怎么修改呢? 搜索到,修改这三个 复制代码 代码如下: upload_max_filesize = 2M post_max_size = 8M memory_limit = 128M 修改完毕 重启下服务,进phpadmin看看吧,应该可

  • phpexcel导入excel处理大数据(实例讲解)

    先下载对应phpExcel 的包就行了https://github.com/PHPOffice/PHPExcel 下载完成 把那个Classes 这个文件夹里面的 文件跟文件夹拿出来就好了. 直接写到PHPExcel 这个文件里面的.调用很简单.引入phpExcel 这个类传递对应的excel 文件的路径就好了 现在上传到指定的目录,然后加载上传的excel文件读取这里读取是的时候不转换数组了.注意:是Sheet可以多个读取,php上传值要设置大,上传超时要设置长. header('Conten

  • php+ajax导入大数据时产生的问题处理

    遇到的问题就从先到后的一一说吧. 问题1 按照我最初的想法,先上传文件再读取文件.这里问题就来了,当文件较大的时候上传较慢,导致客户看到的操作一直处于等待状态,不人性化. 处理办法:我是这样做的,大神有更好的办法,求介绍.我先把文件上传上去,然后把文件存到一个特定的文件夹就叫 import吧   ,然后返回一个这个文件名字.这样就确保了文件是上传成功的.并且我可以在他返回名字的这一步用js  给客户一个提示.然后就是ajax去请求php读取文件,插入数据库.可是问题来了. 问题2 当我用ajax

  • php 大数据量及海量数据处理算法总结

    下面的方法是我对海量数据的处理方法进行了一个一般性的总结,当然这些方法可能并不能完全覆盖所有的问题,但是这样的一些方法也基本可以处理绝大多数遇到的问题.下面的一些问题基本直接来源于公司的面试笔试题目,方法不一定最优,如果你有更好的处理方法,欢迎与我讨论. 1.Bloom filter 适用范围:可以用来实现数据字典,进行数据的判重,或者集合求交集 基本原理及要点: 对于原理来说很简单,位数组+k个独立hash函数.将hash函数对应的值的位数组置1,查找时如果发现所有hash函数对应位都是1说明

  • PHP导出MySQL数据到Excel文件(fputcsv)

    这里的方法是利用fputcsv写CSV文件的方法,直接向浏览器输出Excel文件. 复制代码 代码如下: // 输出Excel文件头,可把user.csv换成你要的文件名 header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename="user.csv"'); header('Cache-Control: max-age=0'); // 从数据库中获取

  • PHP实现实时生成并下载超大数据量的EXCEL文件详解

    前言 最近在工作中接到一个需求,通过选择的时间段导出对应的用户访问日志到excel中, 由于用户量较大,经常会有导出50万加数据的情况.而常用的PHPexcel包需要把所有数据拿到后才能生成excel, 在面对生成超大数据量的excel文件时这显然是会造成内存溢出的,所以考虑使用让PHP边写入输出流边让浏览器下载的形式来完成需求. 我们通过如下的方式写入PHP输出流 $fp = fopen('php://output', 'a'); fputs($fp, 'strings'); .... ...

  • php 在线导入mysql大数据程序

    php 在线导入 mysql 大数据程序 <?php header("content-type:text/html;charset=utf-8"); error_reporting(E_ALL); set_time_limit(0); $file='./test.sql'; $data=file($file); echo "<pre>"; //print_r($data); $data_new=array(); $tmp=array(); fore

  • 浅析THINKPHP的addAll支持的最大数据量

    Thinkphp中的Model操作有两个方法:add()和addAll 复制代码 代码如下: $User = M("User"); // 实例化User对象  $data['name'] = 'ThinkPHP';  $data['email'] = 'ThinkPHP@gmail.com';  $User->add($data);  $dataList[] = array('name'=>'thinkphp','email'=>'thinkphp@gamil.com

  • php使用fputcsv实现大数据的导出操作详解

    本文实例讲述了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 '

  • Java实现Excel导入导出操作详解

    目录 前言 1. 功能测试 1.1 测试准备 1.2 数据导入 1.2.1 导入解析为JSON 1.2.2 导入解析为对象(基础) 1.2.3 导入解析为对象(字段自动映射) 1.2.4 导入解析为对象(获取行号) 1.2.5 导入解析为对象(获取原始数据) 1.2.6 导入解析为对象(获取错误提示) 1.2.7 导入解析为对象(限制字段长度) 1.2.8 导入解析为对象(必填字段验证) 1.2.9 导入解析为对象(数据唯一性验证) 1.3 数据导出 1.3.1 动态导出(基础) 1.3.2 动

  • 使用imp和exp命令对Oracle数据库进行导入导出操作详解

    这里导入导出路径都在D盘下,默认文件名为:example.dmp exp方式导出数据 相关参数项如下: 关键字 说明 默认 USERID 用户名/口令 FULL 导出整个文件 (N) BUFFER 数据缓冲区的大小 OWNER 导出指定的所有者用户名列表 FILE 输出文件 (EXPDAT.DMP) TABLES 导出指定的表名列表 COMPRESS 是否压缩导出的文件 (Y) RECORDLENGTH IO 记录的长度 GRANTS 导出权限 (Y) INCTYPE 增量导出类型 INDEXE

  • Python实现数据的序列化操作详解

    目录 Json 模块 dumps()函数 dump()函数 loads()函数 load()函数 Pickle 模块 dumps()函数 dump()函数 loads()函数 load()函数 总结 ​在日常开发中,对数据进行序列化和反序列化是常见的数据操作,Python提供了两个模块方便开发者实现数据的序列化操作,即 json 模块和 pickle 模块.这两个模块主要区别如下: json 是一个文本序列化格式,而 pickle 是一个二进制序列化格式: json 是我们可以直观阅读的,而 p

  • 30个mysql千万级大数据SQL查询优化技巧详解

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0 3.应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用

  • springboot 使用poi进行数据的导出过程详解

    使用的是idea+restful风格 第一:引入依赖为: <!--poi--> <dependency> <groupId>org.apache.xmlbeans</groupId> <artifactId>xmlbeans</artifactId> <version>2.6.0</version> </dependency> <dependency> <groupId>do

  • Mysql大数据量查询优化思路详析

    目录 1. 千万级别日志查询的优化 2. 几百万黑名单库的查询优化 3. Mybatis批量插入处理问题 项目场景: Mysql大表查询优化,理论上千万级别以下的数据量Mysql单表查询性能处理都是可以的. 问题描述: 在我们线上环境中,出现了mysql几千万级别的日志查询.几百万级别的黑名单库查询分页查询及条件查询都慢的问题,针对Mysql表优化做了一些优化处理. 原因分析:首先说一下日志查询,在Mysql中如果索引加的比较合适,走索引情况下千万级别查询不会超过一秒,Mysql查询的速度和检索

  • MySQL导入与导出备份详解

    目录 一.MySQL备份类型详解 (一)按照备份对数据库的影响分类 (二)按照备份的文件进行分类 (三)按照备份的方式进行分类 二.MySQL数据库导出 (一)mysqldump导出数据 (二)mysqlhotcopy裸文件备份 (三)mysqldump与mysqlhotcopy比较 三.MySQL数据库导入 总结 一.MySQL备份类型详解 对于现代互联网公司而言,存储在服务器数据库中的数据,逐步成为企业和公司的命脉,对企业和公司的生存发展具有十分重大的影响.为了保证数据库数据存储安全,确保不

  • 对python中大文件的导入与导出方法详解

    1.csv文件的导入和导出 通过一个矩阵导出为csv文件,将csv文件导入为矩阵 将csv文件导入到一个矩阵中 import numpy my_matrix = numpy.loadtxt(open("c:\\1.csv","rb"),delimiter=",",skiprows=0) 将矩阵导出到本地csv中 numpy.savetxt('new.csv', my_matrix, delimiter = ',') 未完待续... 也可以使用pi

  • C语言 数据存储方式知识点详解

    C语言 数据存储方式 一.源码 一个数的原码(原始的二进制码)有如下特点: 最高位做为符号位,0表示正,为1表示负 其它数值部分就是数值本身绝对值的二进制数 负数的原码是在其绝对值的基础上,最高位变为1 下面数值以1字节的大小描述: 十进制数 原码 +15 0000 1111 -15 1000 1111 +0 0000 0000 -0 1000 0000 注:原码表示法简单易懂,与带符号数本身转换方便,只要符号还原即可,但当两个正数相减或不同符号数相加时,必须比较两个数哪个绝对值大,才能决定谁减

随机推荐