一、 前言
财务在每月月底做财务数据统计时,需要统计每月产品的出货单及退货单报表数据,故要求在每月月底要汇总当月的报表数据,每一季度或者半年也要相应的统计报表数据,并能把数据导出到excl表格,所以数据报表导出功能则是必然的。财务提供的excel表格字段繁多,汇总下关联到数据库表达到7张以上,故在进行出货单或者退货单报表查询之时,由于涉及到多张表关联,故每次查询都需要耗费相当多的时间和空间。
二、 实现
数据报表只需要按照起始时间和结束时间进行查询和导出。以出货单为例,历史数据累计至今的出货单以上万至几十万之多。早期的导出功能是实时查询并导出,在选择时间段进行数据导出之时,如果时间跨度太大,后台执行太久的话会导致前端页面显示错误信息,或者等待时间过长让财务人员误以为导出失败,用户体验也不是很好。
三、 优化
a) 从服务器架设上优化
考虑到我们是采用LAMP的服务器架构,PHP是部署到Linux环境下,可以尝试利用Linux提供的工具配合PHP使用。
用户使用的场景主要是财务人员查询的基本上都是历史或者已成型的数据,故我们可以在服务器空闲期间使用PHP-CLI方式后台执行生成数据并插入到新设计的数据表中,用户在使用过程中可以选取缓存数据导出报表的方式来生成excel数据。借助于Linux环境下Crontab工具可以实现此情景。具体的Crontab命令参考如下:
/usr/local/php-5.4.26/bin/php
-f /data/www/wms/index.php cli/crontab_report/export_to_db
b) 分批执行
后台执行Crontab命令之时,如果一次性把所有数据通过SQL检索出来再进行插入的话,在中间如果出现异常退出之时,则会导致前期所做的工作付之流水。且PHP本身在执行期间是会耗费内存的,是有可能出现异常退出的情况,故可以采用类似分页查询的方式对数据进行分批处理并插入。目前采用的是每一批次采用300条出货单检索并插入。
c) PHP执行内存设置
在PHP脚本执行期间,是有内存消耗的,正常情况下在PHP执行完脚本之后会自动释放相应内存,但如果当前执行的脚本将要花很长时间并占用比较大的资源之时,则会导致PHP执行内存达到一定上限而导致异常退出。使用PHP提供的memory_get_usage()函数我们可以查看在后台执行PHP脚本所耗费的内存。采用上述B分批执行方式,每一批次采用300条数据检索并插入,计算出内存差可算出检索出300条记录需要耗费大致1.6M内存,插入操作消耗128K数据,查询PHP配置参数memory_limit为96M,实际可插入数据13000-15000左右数据之后则会异常退出,并且查不出错误信息。
我们可以通过增大memory_limit参数值来延长PHP执行时间,有三种方式可以设置此参数,一种是修改php.ini中的memory_limit参数,此方式对整个php环境影响较大,也可以使用ini_set()函数临时设置为指定的memory_limit大小,同样的在相应网站有.htaccess文件的时候也可以修改类似如下php_value memory_limit 16M。实际测试环境下,通过ini_set设置memory_limit为256M之时,实际可插入的数据达到42077条。
d) 执行期间实时释放相应内存
上述C方式是采用扩大memory_limit的值来延长PHP的执行时间,但仍不可避免有些历史数据是无法生成的,表现为只能缓存之前4-5个月数据,当然此情况也基本满足要求。上述提到在检索300条记录时需要耗费1.7M内存,这消耗的资源是挺大的,我们可以采用类似C语言的方式,在不需要的时候把它释放掉,上述情景主要都是与数据库相关,我们只要保证在检索到相应参数并确认此在后续无用之时把他释放掉,相应PHP函数是mysql_free_result,CI框架已做了封装,调用CI的free_result函数即可。同样的相应的数据在使用完之后可以通过unset函数来释放相应的PHP内存。
四、 参考文档
http://blog.chinaunix.net/uid-17085332-id-2832158.html
2)PHP查看内存使用情况:
http://blog.csdn.net/duotuu/article/details/7554207