php使用yield進(jìn)行大數(shù)據(jù)量處理
目錄 隱藏
1 概述
2 生成器函數(shù)
3 yield關(guān)鍵字
4 一個(gè)簡(jiǎn)單的例子
5 遍歷數(shù)據(jù)庫(kù)實(shí)例
5.1 未使用生成器
5.2 使用生成器
概述
當(dāng)我們需要使用php來(lái)處理大數(shù)據(jù)量時(shí),例如循環(huán)數(shù)據(jù)庫(kù)的所有記錄,這個(gè)記錄可能會(huì)很大,例如100萬(wàn)行,那么通過(guò)傳統(tǒng)的辦法就行不通了。首先通過(guò)web訪問(wèn),php有超時(shí)時(shí)間,默認(rèn)是30秒。那么就只能通過(guò)php cli的方式來(lái)執(zhí)行,這樣就沒(méi)有超時(shí)時(shí)間了,但由于數(shù)據(jù)量太大,php循環(huán)時(shí)需要將數(shù)據(jù)全部載入內(nèi)存中執(zhí)行,由于數(shù)據(jù)量太大,php會(huì)報(bào)Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes)的錯(cuò)誤。php默認(rèn)的內(nèi)存限制為128M,雖然可以通過(guò)修改php.ini中memory_limit的選項(xiàng)的值來(lái)提高內(nèi)存限制,但始終不是最優(yōu)的解決辦法。PHP通過(guò)生成器函數(shù)可以極大節(jié)省內(nèi)存開銷。
生成器函數(shù)
生成器函數(shù)看起來(lái)像普通函數(shù)——不同的是普通函數(shù)返回一個(gè)值,而生成器可以 yield 生成多個(gè)想要的值。任何包含 yield 的函數(shù)都是一個(gè)生成器函數(shù)。
當(dāng)一個(gè)生成器被調(diào)用的時(shí)候,它返回一個(gè)可以被遍歷的對(duì)象.當(dāng)你遍歷這個(gè)對(duì)象的時(shí)候(例如通過(guò)一個(gè)foreach循環(huán)),PHP 將會(huì)在每次需要值的時(shí)候調(diào)用對(duì)象的遍歷方法,并在產(chǎn)生一個(gè)值之后保存生成器的狀態(tài),這樣它就可以在需要產(chǎn)生下一個(gè)值的時(shí)候恢復(fù)調(diào)用狀態(tài)。
yield關(guān)鍵字
生成器函數(shù)的核心是yield關(guān)鍵字。yield關(guān)鍵字看起來(lái)像一個(gè)return申明,不同之處在于普通return會(huì)返回值并終止函數(shù)的執(zhí)行,而yield會(huì)返回一個(gè)值給循環(huán)調(diào)用此生成器的代碼并且只是暫停執(zhí)行生成器函數(shù)。
一個(gè)簡(jiǎn)單的例子
以上例子會(huì)輸出:
遍歷數(shù)據(jù)庫(kù)實(shí)例
例如當(dāng)前我們需要循環(huán)數(shù)據(jù)庫(kù)的emp表,這個(gè)表中有100萬(wàn)行記錄,我們需要循環(huán)并修改mgr的字段的值。
未使用生成器
這在數(shù)據(jù)量小時(shí)并沒(méi)有什么問(wèn)題,但數(shù)據(jù)量比較大的話,就無(wú)法執(zhí)行了,會(huì)報(bào)內(nèi)存超過(guò)限制的錯(cuò)誤。
使用生成器
通過(guò)test_yield這個(gè)生成器函數(shù),程序可以正常執(zhí)行,且內(nèi)存不會(huì)超限。
