在Laravel中使用cursor來查詢並處理資料 (輕鬆處理千萬級的資料)

zhonglang發表於2020-12-24

Laravel中使用cursor來查詢並處理資料 (輕鬆處理千萬級的資料)


事發現場

最近在專案中遇到記憶體不足的問題, 測試環境中的PHP記憶體只有64M,在匯出的時候, 資料量比較大,這個時候會出現記憶體溢位的錯誤.

如何解決

目前想到兩種方法:

  1. 調整php.ini檔案中memory_limit配置項; 或者在呼叫方法中調整記憶體大小ini_set('memory_limit', "").
  2. 使用LaravelLazy Collection.

考慮到修改配置檔案的影響範圍過大, 以及對匯出的實時性要求不是很高, 所以我們選擇了第二種方法.

Lazy Collection

如何使用Lazy Collection? 很簡單, 將查詢構建器鏈末尾的get()更改為cursor()就好了 !

cursor ( )

  • cursor的原理

    cursor的實現使用了 yield 關鍵字, yield關鍵字是生成器函式的核心, 它的呼叫形式跟return很像, 不同之處在於return會返回值並且終止函式執行, 而yield會返回值給迴圈呼叫生成器的程式碼並且只是暫停生成器函式.

  • cursor()的程式碼如下

      /**
       * Get a generator for the given query.
       *
       * @return \Generator
       */
      public function cursor()
      {
          foreach ($this->applyScopes()->query->cursor() as $record) {
              yield $this->newModelInstance()->newFromBuilder($record);
          }
      }

由於使用了yield關鍵字, 在迴圈cursor生成器的時候,可以漸進式的處理資料,即使在記憶體很小的情況下,也可以輕鬆處理千萬級的資料! 真的是非常方便哦!

本作品採用《CC 協議》,轉載必須註明作者和本文連結
堅定地後端開發者

相關文章