2016-09-26 07:19:03 li905663280 阅读数 1196
  • PHP7会话控制

    King老师精心打造的PHP7会话控制课程,由浅入深的讲解了PHP中的会话控制思想,解决方案,详细剖析了PHP中的session和cookie的使用,并通过实战案例进行实战演练,让我们一起开启会话控制之旅吧~ 山哥出品,必属精品!

    16714 人正在学习 去看看 何山

医院大数据解决方案

expalin

众多的数据库,不同的表结构,众多的接口,怎么解决。

step

1.hie 为医院大数据提供了解决的方案,从不同的数据库,根据表结构提取。减小的接口的开发。

refs

http://www.servicecare.cn/index.php?m=content&c=index&a=lists&catid=19


last update 2016-09-26

2018-05-20 17:11:48 qq_28510439 阅读数 913
  • PHP7会话控制

    King老师精心打造的PHP7会话控制课程,由浅入深的讲解了PHP中的会话控制思想,解决方案,详细剖析了PHP中的session和cookie的使用,并通过实战案例进行实战演练,让我们一起开启会话控制之旅吧~ 山哥出品,必属精品!

    16714 人正在学习 去看看 何山

作者在一次工作中需要导出一份10多万数据的csv文件,导出过程中出现时php超时的问题,下面提供下个人的解决方案:

1.  使用分页检索数据库,首先在页面中获取到页数及在服务器中生成一个只有title的csv文件

2.  在页面中js循环调用ajax,循环次数为之前获取到的页数,在ajax调用的页面中根据条件查询出数据,fwrite写入到csv文件中

3. 这样多次循环后生成完整的csv文件,完成后跳转到另一页面中,页面中访问csv文件地址,读取内容

4. 将内容echo出来,就提示用户下载文件了

5.  最后删除csv文件即可


重点在于循环调用ajax写入csv文件

2019-02-12 18:42:52 Zhihua_W 阅读数 7306
  • PHP7会话控制

    King老师精心打造的PHP7会话控制课程,由浅入深的讲解了PHP中的会话控制思想,解决方案,详细剖析了PHP中的session和cookie的使用,并通过实战案例进行实战演练,让我们一起开启会话控制之旅吧~ 山哥出品,必属精品!

    16714 人正在学习 去看看 何山

综述

最近在工作中遇到这样一个问题,公司项目要求订单有导出功能,以前虽然也使用PHPExcel做过几个导出功能,但是这次所需导出的数量巨大,因此在开发中遇到一些导出的坑,在此进行总结记录一下。

吐槽

首先,我们可以肯定这个需求太XX(手动和谐)了,这么大的数据量让谁看这去分析啊?一般的Excel数据都是给市场、财务的的非技术部门使用的,所以,我认为应该把思路首先放到为什么需要导出这类数据上,根据需求来解决问题。毕竟不是甲方(出钱的),改变不了需求就只能老老实实的实现具体功能了。请看下面解决方案。

分析

1、工具

首先明确我们需要导出的数量50W+,其次我们使用过都知道Excel2003版最大行数是65535行,Excel2007版的行数(1048576行)才能达到我们的要求,所以我们需要使用Excel的版本必须为2007版及以上。

2、类库

目前最常用的PHP处理Excel的类库是PHPExcel(经实例测试导出1w条数据,再加上各种数据判断处理我用了5-8分钟);我在网上还查到一款叫PHPOffice(这个我没用过,大家可以尝试一下,据说效率比PHPExcel要好,等下次再写篇博文介绍一下);还有一个fputcsv(),导出的是csv格式文件,也可以用Excel文件打开。

各种坑

1、超时

这个是直接的,请求超时。在这个多的数据请求处理下,超市非常常见,这时我们需要修改PHP的配置:set_time_limit(0)。

2、溢出

我们一次性的把所有数据从数据库取出填充到内存中,一下不光内存存储不够,并且如果服务器CPU配置不高的话使用率一下也能达到100%,会造成服务器卡负载。关于溢出我们也需要修改PHP的配置:ini_set('memory_limit', '1024M')。

解决方案

1、使用PHPExcel导出

使用此种方案一下导出50w+的数据体验非常的不好,经测试之后是虽说是可行的,服务器上也可以导出,就是时间会慢一些,而且会是一直下载状态。如果使用php类库,建议将php升级到最新的php7版本节省内存,且计算速度要快

2、使用csv导出

如果不是用php类库,那么fputcsv()是最佳方式,这种方式要比PHPExcel好很多;因为csv文件较小,csv文件数据可存放数量可大可小,csv生成不占用大量CPU和时间,而Excel的生成时间随着文件数据量的增加成而所需时间越多。

3、理想方案

将数据按照某种条件进行分割,减少导出的数据量,例如按照日期进行导出,可一周导出一次或者一天导出一次,数据分割肯定是必须的步骤,防止内存溢出,运行超时;

进行算法优化,在数据循环时,减少嵌套循环,生成csv或者Excel的数据对象时,一次成型,减少数据库查询次数,如果需要用到其他数据请提前生成相应数据结构的数据。

4、最快方案

将需求交给运维,直接运行sql语句进行导出:

SELECT
	*
FROM
	table_name 
INTO OUTFILE 'F:/test.csv' 
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY '\r\n';

运行此语句可能出现如下错误:

The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

这个是由于Mysql的配置权限问题,可以运行SHOW VARIABLES LIKE '%secure%';查看 secure-file-priv 当前的值是什么,NULL就代表禁止导出,所以需要设置一下。在Mysql安装路径下的my.ini文件,修改设置一下路径,没有的话添加上此配置:

secure_file_priv=F:/

50w+的数据你会发现很快就导出了。你也可以写此此语句,知道此文件在服务器上的路径,进行打包下载即可。

2016-12-14 18:42:19 Register_man 阅读数 3146
  • PHP7会话控制

    King老师精心打造的PHP7会话控制课程,由浅入深的讲解了PHP中的会话控制思想,解决方案,详细剖析了PHP中的session和cookie的使用,并通过实战案例进行实战演练,让我们一起开启会话控制之旅吧~ 山哥出品,必属精品!

    16714 人正在学习 去看看 何山

PHP ajax访问服务器 $_SESSION数据丢失解决方案

如果在使用php需要保存session数据,在其他PHP页面进行访问的话,需要在该php文件开头添加代码“session_start();”
示例如下:

$.ajax({
    url:"ajax_query.php",
    type:"GET",
    success:function (data) {
        $("#times").text(data);
    }
});

ajax_query.php:

<?php
session_start();
if(isset($_SESSION['query']))
{
    ++$_SESSION['query'];
}
else
{
    $_SESSION['query']=1;
}
echo $_SESSION['query'];
?>
2014-03-17 16:58:46 cdy102688 阅读数 6649
  • PHP7会话控制

    King老师精心打造的PHP7会话控制课程,由浅入深的讲解了PHP中的会话控制思想,解决方案,详细剖析了PHP中的session和cookie的使用,并通过实战案例进行实战演练,让我们一起开启会话控制之旅吧~ 山哥出品,必属精品!

    16714 人正在学习 去看看 何山

背景:接手的项目中支持导出一批数据,全数量在50W左右。在接手的时候看代码是直接一次查询mysql获得数据,然后用header函数直接写入csv,用户开始导出则自动下载。但是,在全导出的时候,功能出现了BUG问题。

1.数据量大导致php处理脚本运行时间,超过默认限制。

2.数据量过大,导致内存溢出,流程中止。


初版解决方案:

1.通过函数set_time_limit(0);       取消执行时间限制(在导出的函数入口设置,这是合理的,导出的数据量过大了)

2.关于数据过大,内存溢出的解决办法,开始是想到了php动态变量(先由sql语句获得总记录数,然后每2W条切分,查询2w条数据存入一个变量)

	$total_export_count = $db->getOne("select count(1) from ($sql) t2");
		
	for ($i=0;$i<intval($total_export_count/20000)+1;$i++){
	        $export_data = "exportdata".$i;
    	    $$export_data = $db->getAll($sql." limit ".strval($i*20000).",20000");
    	}
然后通过相应的代码取出变量的信息,echo到csv文件中,这种方式在本地测试的时候是通过的,但在服务器上依旧会内存溢出。
	header ( "Content-type:application/vnd.ms-excel" );
    	header ( "Content-Disposition:filename=" . iconv ( "UTF-8", "GB18030", "查询用户列表" ) . ".csv" );	
    	$out = $column_name;
    	echo iconv ( "UTF-8", "GB18030", $out );
    	
    	for ($i=0;$i<intval($total_export_count/20000)+1;$i++){
    	    $dynamic_name = "exportdata".$i;
        	foreach ( $$dynamic_name as $key => $item ) {
        	    echo iconv ( "UTF-8", "GB18030", "\n".implode(',',$item) );
        	}
        	
        	// 将已经写到csv中的数据存储变量销毁,释放内存占用
            	unset($$dynamic_name);
    	}
    	
    	exit ();
因为上面的方法在服务器上没有通过,所以只能将分割数据量的操作放到写文件的流程中,相比上面的思路这种会慢一些。
    	header ( "Content-type:application/vnd.ms-excel" );
    	header ( "Content-Disposition:filename=" . iconv ( "UTF-8", "GB18030", "查询用户列表" ) . ".csv" );	
    	$out = $column_name;
    	echo iconv ( "UTF-8", "GB18030", $out );
    	
    	$pre_count = 20000;
    	for ($i=0;$i<intval($total_export_count/$pre_count)+1;$i++){
    	    $export_data = $db->getAll($sql." limit ".strval($i*$pre_count).",{$pre_count}");
        	foreach ( $export_data as $key => $item ) {
        	    echo iconv ( "UTF-8", "GB18030", "\n".implode(',',$item) );
        	}
        	
        	// 将已经写到csv中的数据存储变量销毁,释放内存占用
            unset($export_data);
    	}
    	
    	exit ();
经测试之后是可行的,服务器上也可以导出,就是时间会慢一些,而且会是一直下载状态。

关于这个场景整理了一些资料:

1.csv文件的条数是好像没有限制的,可以一直写(网上的博文里面看的,没证实过)

2.excel 2010版本以上,是可以读取100多W行数据的(验证过,新建一个excel,ctrl+下箭头  到文件末尾可以看到行数)


理想的解决方案(没有具体实施,想的)

1.数据分割肯定是必须的步骤,防止内存溢出。

2.将分割后的数据写入到一个excel或者一个csv文件中,被分割了多少次,写多少个文件。这样可以防止达到文件行数的最大限制。

3.将2中写的文件进行压缩处理,压缩成一个压缩包,然后进行自动下载。


补充:

在上面的方案正式运行的时候发现导出的数据,总是比查询的总记录数要少1000多条,几次看数据后发现有些数据并没有换行,而是写到上一行去了。在有了这个觉悟后,重新看了遍之前转别人的帖子,发现还是用fputcsv()函数比较靠谱,传入一个数组,作为一行的数据,由该函数自己去写换行和控列。感觉有些时候还是不要偷懒的好啊,虽然自己写","完成列分割,写"\n"完成空格,貌似是可行的,但是对于一些数据,并不一定能控制的好。


修改后的导出代码:

    	header ( "Content-type:application/vnd.ms-excel" );
    	header ( "Content-Disposition:filename=" . iconv ( "UTF-8", "GB18030", "query_user_info" ) . ".csv" );
    	
    	// 打开PHP文件句柄,php://output 表示直接输出到浏览器
    	$fp = fopen('php://output', 'a'); 
    	
    	// 将中文标题转换编码,否则乱码
    	foreach ($column_name as $i => $v) {  
            $column_name[$i] = iconv('utf-8', 'GB18030', $v);  
        }
        // 将标题名称通过fputcsv写到文件句柄  
        fputcsv($fp, $column_name);
    	
    	$pre_count = 10000;
    	for ($i=0;$i<intval($total_export_count/$pre_count)+1;$i++){
    	    $export_data = $db->getAll($sql." limit ".strval($i*$pre_count).",{$pre_count}");
        	foreach ( $export_data as $item ) {
        	    $rows = array();
        	    foreach ( $item as $export_obj){
        	        $rows[] = iconv('utf-8', 'GB18030', $export_obj);
        	    }
    	        fputcsv($fp, $rows);
        	}
        	
        	// 将已经写到csv中的数据存储变量销毁,释放内存占用
            unset($export_data);
            ob_flush();
            flush();
    	}
    	
    	exit ();

没有更多推荐了,返回首页