PHPExcel导出大量数据超时及内存错误解决方法

matiantian 2014-10-30

PHP导出excel相对很多童鞋都碰到了,使用phpexcel类也确实方便,但导出大数据的时候就没那么简单了,常常会伴随一些超时或内存溢出的问题,下面就给大家介绍一些方法,共同学习,共同进步。。。

PHPExcel是一个很强大的处理Excel的PHP开源类,但是很大的一个问题就是它占用内存太大,从1.7.3开始,它支持设置cell的缓存方式,但是推荐使用目前稳定的版本1.7.6,因为之前的版本都会不同程度的存在bug,以下是其官方文档:

PHPExcel1.7.6官方文档写道

PHPExcelusesanaverageofabout1k/cellinyourworksheets,solargeworkbookscanquicklyuseupavailablememory.CellcachingprovidesamechanismthatallowsPHPExceltomaintainthecellobjectsinasmallersizeofmemory,ondisk,orinAPC,memcacheorWincache,ratherthaninPHPmemory.Thisallowsyoutoreducethememoryusageforlargeworkbooks,althoughatacostofspeedtoaccesscelldata.

PHPExcel平均下来使用1k/单元格的内存,因此大的文档会导致内存消耗的也很快。单元格缓存机制能够允许PHPExcel将内存中的小的单元格对象缓存在磁盘或者APC,memcache或者Wincache中,尽管会在读取数据上消耗一些时间,但是能够帮助你降低内存的消耗。

PHPExcel1.76.官方文档写道

Bydefault,PHPExcelstillholdsallcellobjectsinmemory,butyoucanspecifyalternatives.Toenablecellcaching,youmustcallthePHPExcel_Settings::setCacheStorageMethod()method,passinginthecachingmethodthatyouwishtouse.

默认情况下,PHPExcel依然将单元格对象保存在内存中,但是你可以自定义。你可以使用PHPExcel_Settings::setCacheStorageMethod()方法,将缓存方式作为参数传递给这个方法来设置缓存的方式。

Php代码:

$cacheMethod=PHPExcel_CachedObjectStorageFactory::cache_in_memory;

PHPExcel_Settings::setCacheStorageMethod($cacheMethod);

PHPExcel1.7.6官方文档写道

setCacheStorageMethod()willreturnabooleantrueonsuccess,falseonfailure(forexampleiftryingtocachetoAPCwhenAPCisnotenabled).

setCacheStorageMethod()方法会返回一个BOOL型变量用于表示是否成功设置(比如,如果APC不能使用的时候,你设置使用APC缓存,将会返回false)

PHPExcel1.7.6官方文档写道

Aseparatecacheismaintainedforeachindividualworksheet,andisautomaticallycreatedwhentheworksheetisinstantiatedbasedonthecachingmethodandsettingsthatyouhaveconfigured.Youcannotchangetheconfigurationsettingsonceyouhavestartedtoreadaworkbook,orhavecreatedyourfirstworksheet.

每一个worksheet都会有一个独立的缓存,当一个worksheet实例化时,就会根据设置或配置的缓存方式来自动创建。一旦你开始读取一个文件或者你已经创建了第一个worksheet,就不能在改变缓存的方式了。

PHPExcel1.7.6官方文档写道

Currently,thefollowingcachingmethodsareavailable.

目前,有以下几种缓存方式可以使用:

Php代码:

PHPExcel_CachedObjectStorageFactory::cache_in_memory;

PHPExcel1.7.6官方文档写道

Thedefault.Ifyoudon’tinitialiseanycachingmethod,thenthisisthemethodthatPHPExcelwilluse.CellobjectsaremaintainedinPHPmemoryasatpresent.

默认情况下,如果你不初始化任何缓存方式,PHPExcel将使用内存缓存的方式。

===============================================

Php代码:

PHPExcel_CachedObjectStorageFactory::cache_in_memory_serialized;

PHPExcle1.7.6官方文档写道

Usingthiscachingmethod,cellsareheldinPHPmemoryasanarrayofserializedobjects,whichreducesthememoryfootprintwithminimalperformanceoverhead.

使用这种缓存方式,单元格会以序列化的方式保存在内存中,这是降低内存使用率性能比较高的一种方案。

===============================================

Php代码:

PHPExcel_CachedObjectStorageFactory::cache_in_memory_gzip;

PHPExcel1.7.6官方文档写道

Likecache_in_memory_serialized,thismethodholdscellsinPHPmemoryasanarrayofserializedobjects,but-gzippedtoreducethememoryusagestillfurther,althoughaccesstoreadorwriteacellisslightlyslower.

与序列化的方式类似,这种方法在序列化之后,又进行gzip压缩之后再放入内存中,这回跟进一步降低内存的使用,但是读取和写入时会有一些慢。

===========================================================

Php代码:

PHPExcel_CachedObjectStorageFactory::cache_to_discISAM;

PHPExcel1.7.6官方文档写道

Whenusingcache_to_discISAMallcellsareheldinatemporarydiskfile,withonlyanindextotheirlocationinthatfilemaintainedinPHPmemory.Thisisslowerthananyofthecache_in_memorymethods,butsignificantlyreducesthememoryfootprint.Thetemporarydiskfileisautomaticallydeletedwhenyourscriptterminates.

当使用cache_to_discISAM这种方式时,所有的单元格将会保存在一个临时的磁盘文件中,只把他们的在文件中的位置保存在PHP的内存中,这会比任何一种缓存在内存中的方式都慢,但是能显著的降低内存的使用。临时磁盘文件在脚本运行结束是会自动删除。

===========================================================

Php代码:

PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;

PHPExcel1.7.6官方文档写道

Likecache_to_discISAM,whenusingcache_to_phpTempallcellsareheldinthephp://tempI/Ostream,withonlyanindextotheirlocationmaintainedinPHPmemory.InPHP,thephp://memorywrapperstoresdatainthememory:php://tempbehavessimilarly,butusesatemporaryfileforstoringthedatawhenacertainmemorylimitisreached.Thedefaultis1MB,butyoucanchangethiswheninitialisingcache_to_phpTemp.

类似cache_to_discISAM这种方式,使用cache_to_phpTemp时,所有的单元格会还存在php://tempI/O流中,只把他们的位置保存在PHP的内存中。PHP的php://memory包裹器将数据保存在内存中,php://temp的行为类似,但是当存储的数据大小超过内存限制时,会将数据保存在临时文件中,默认的大小是1MB,但是你可以在初始化时修改它:

Php代码:

$cacheMethod=PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;

$cacheSettings=array(’memoryCacheSize’=>’8MB’);

PHPExcel_Settings::setCacheStorageMethod($cacheMethod,$cacheSettings);

PHPExcel1.7.6官方文档写道

Thephp://tempfileisautomaticallydeletedwhenyourscriptterminates.

php://temp文件在脚本结束是会自动删除。

===========================================================

Php代码:

PHPExcel_CachedObjectStorageFactory::cache_to_apc;

PHPExcle1.7.6官方文档写道

Whenusingcache_to_apc,cellobjectsaremaintainedinAPCwithonlyanindexmaintainedinPHPmemorytoidentifythatthecellexists.Bydefault,anAPCcachetimeoutof600secondsisused,whichshouldbeenoughformostapplications:althoughitispossibletochangethiswheninitialisingcache_to_APC.

当使用cach_to_apc时,单元格保存在APC中,只在内存中保存索引。APC缓存默认超时时间时600秒,对绝大多数应用是足够了,当然你也可以在初始化时进行修改:

Php代码:

$cacheMethod=PHPExcel_CachedObjectStorageFactory::cache_to_APC;

$cacheSettings=array(’cacheTime’=>600);

PHPExcel_Settings::setCacheStorageMethod($cacheMethod,$cacheSettings);

PHPExcel1.7.6官方文档写道

WhenyourscriptterminatesallentrieswillbeclearedfromAPC,regardlessofthecacheTimevalue,soitcannotbeusedforpersistentstorageusingthismechanism.

当脚本运行结束时,所有的数据都会从APC中清楚(忽略缓存时间),不能使用此机制作为持久缓存。

===========================================================

Php代码:

PHPExcel_CachedObjectStorageFactory::cache_to_memcache

PHPExcel1.7.6官方文档写道

Whenusingcache_to_memcache,cellobjectsaremaintainedinmemcachewithonlyanindexmaintainedinPHPmemorytoidentifythatthecellexists.

Bydefault,PHPExcellooksforamemcacheserveronlocalhostatport11211.Italsosetsamemcachetimeoutlimitof600seconds.Ifyouarerunningmemcacheonadifferentserverorport,thenyoucanchangethesedefaultswhenyouinitialisecache_to_memcache:

使用cache_to_memory时,单元格对象保存在memcache中,只在内存中保存索引。默认情况下,PHPExcel会在localhost和端口11211寻找memcache服务,超时时间600秒,如果你在其他服务器或其他端口运行memcache服务,可以在初始化时进行修改:

Php代码:

$cacheMethod=PHPExcel_CachedObjectStorageFactory::cache_to_memcache;

$cacheSettings=array(’memcacheServer’=>’localhost’,

‘memcachePort’=>11211,

‘cacheTime’=>600

);

PHPExcel_Settings::setCacheStorageMethod($cacheMethod,$cacheSettings);

从初始化设置的形式上看,MS还不支持多台memcache服务器轮询的方式,比较遗憾。

PHPExcel1.7.6官方文档写道

Whenyourscriptterminatesallentrieswillbeclearedfrommemcache,regardlessofthecacheTimevalue,soitcannotbeusedforpersistentstorageusingthismechanism.

当脚本结束时,所有的数据都会从memcache清空(忽略缓存时间),不能使用该机制进行持久存储。

===========================================================

Php代码:

PHPExcel_CachedObjectStorageFactory::cache_to_wincache;

PHPExcel1.7.6官方文档写道

Whenusingcache_to_wincache,cellobjectsaremaintainedinWincachewithonlyanindexmaintainedinPHPmemorytoidentifythatthecellexists.Bydefault,aWincachecachetimeoutof600secondsisused,whichshouldbeenoughformostapplications:althoughitispossibletochangethiswheninitialisingcache_to_wincache.

使用cache_towincache方式,单元格对象会保存在Wincache中,只在内存中保存索引,默认情况下Wincache过期时间为600秒,对绝大多数应用是足够了,当然也可以在初始化时修改:

Php代码:

$cacheMethod=PHPExcel_CachedObjectStorageFactory::cache_to_wincache;

$cacheSettings=array(’cacheTime’=>600);

PHPExcel_Settings::setCacheStorageMethod($cacheMethod,$cacheSettings);

PHPExcel官方文档1.7.6写道

WhenyourscriptterminatesallentrieswillbeclearedfromWincache,regardlessofthecacheTimevalue,soitcannotbeusedforpersistentstorageusingthismechanism.

PHPExcel还是比较强大的,最大的问题就是内存占用的问题,PHPExcel啥时候能出一个轻量级的版本,不需要那么多花哨的功能,只需要导出最普通的数据的版本就好了!

以上内容是LZ在网上找的一篇比较不错的文章,虽没有彻底解决我的问题,但感觉写的不错,谨以此作为笔记,希望对看到的童鞋能够有所帮助!

相关推荐