What is chunk
可以將 chunk 理解成…
我將一大組資料分「塊」處理,
而不是逐筆處理
Why chunk
假設每筆就要執行一段SQL,
這樣我 5000筆資料,就要執行 5000次
如果我將這 5000 筆,每 500 分成一塊,我只要執行 10 次。
如此一來可以有效縮減執行時間也降低了DB的負擔。
How to chunk
Laravel chunk 分成三種
- Query Builder chunk
- Eloquent chunk
- Collection chunk
假設情境
當我有好幾萬的會員,每年要贈送 100點的點數給他們,
我們建立了一個排程,每年1月1日贈送,
隨著會員數量的增加,執行時間會愈來愈久,
我們必須著手優化這段排程 …
Original (No chunk)
當我們沒有chunk通常都是逐筆寫入
這邊用 each
作為範例
|
|
Query Builder chunk
可參考 文件
使用方式和 Eloquent chunk 相同
所以我會在下方 Eloquent chunk 共同解釋
Eloquent chunk
可參考 官方文件
|
|
運作的方式是用 SQL ,
使用 limit 500 offset 0
、 limit 500 offset 500
….. 直到分完全部
在 query 當下就分塊。
Collection chunk
可參考 官方文件
|
|
運作的方式是先都 query出來,再用 php 整理的,
如圖所示
比較
老實說使用哪一個其實感覺不出來,
因為執行效率差不多,
Eloquent 吃DB資源,Collection 吃記憶體資源,
Collection chunk 遇過直接網頁執行,記憶體吃掛了的問題,
最後我還是選擇了 Eloquent chunk
雖然 執行的SQL多了一些 query,但不會吃你記憶體,
也是看大家取捨拉 ~
這是我執行3千筆的資訊
資料量 | 運用 | 花費時間 | 記憶體 |
---|---|---|---|
3000筆 | Original (No chunk) | 6.6s | 142MB |
3000筆 | Eloquent chunk | 1.52s | 33MB |
3000筆 | Collection chunk | 1.49s | 141MB |
題外話
這裡的寫入使用了 Point::insert
為何不使用 Point::create
?
是為了批次寫入及效率的問題考量,
之後再來聊聊 Laravel insert & Laravel create 差異吧