Laravel Model查詢結果的3種儲存格式記憶體佔用對比

斌哥tobin發表於2020-09-21

PHP Laravel框架支援Model查詢資料後可以有多種方式返回資料,對新手會造成一些困擾,比如陣列Model物件、集合、純陣列
今天從記憶體佔用的角度對比一下3種資料返回方式

按陣列Model物件返回資料

  • 寫法
TestModel::query()->where('field_name', $value)->limit(10)->get()->all();

按集合返回資料

  • 寫法
TestModel::query()->where('field_name', $value)->limit(10)->get();

按純陣列返回資料

  • 寫法
TestModel::query()->where('field_name', $value)->limit(10)->get()->toArray();

測試環境

PHP 7.2.28, Docker Compose, MacOS

對比資料

  • 按數量分別取10、100、1000、10000行資料來對比
返回格式 查詢行數 查詢結果記憶體佔用
Model陣列 10 433.2109K
array 10 457.5313K
Collection 10 433.2891K
Model陣列 100 803.3984K
array 100 816.4688K
Collection 100 803.4766K
Model陣列 1000 4.3761M
array 1000 4.2790M
Collection 1000 4.3762M
Model陣列 10000 40.4700M
array 10000 39.2743M
Collection 10000 40.4701M

結論

  1. 資料量在100以內時,用Model陣列佔用記憶體還更少
  2. Collection總比Model陣列多一點點是因為Collection集合多了一層物件包裝儲存Model陣列,有點雞肋,所以我很少用這種方式
  3. Model陣列配置IDE輔助提示時開發效率更高,並且記憶體佔用相比純陣列array相差不大,所以建議用Model陣列方式

開發建議

從開發效率和維護角度我建議選擇Model陣列的開發方式
因為在PhpStorm這個IDE中,Model的查詢方法中加入註釋 @return static[] 就可以有IDE欄位輔助
當然前提是在相應Model的註釋中加入屬性註釋 @property,下方給出幾個示例

Model @property 示例

/**
 * @property int $id 主鍵ID
 * @property string $order_sn 訂單號
 */
class OrderInfoModel extends Model
{
    protected $table = 'order_info';
    public $timestamps = false;
      /**
      單例入口
      */
    public static function singleton()
    {
        return app(static::class);
    }
      /**
     * 查詢訂單
     * @param string $sn
     * @return static
     */
    public function findBySn($sn)
    {
        return static::query()->where('order_sn', $sn)->first();
    }
      /**
     * 查詢訂單列表
     * @return static[]
     */
    public function findListByPage($page, $pageSize)
    {
        return static::query()->forPage($page, $pageSize)->get()->all();
    }
}
//注意兩個方法的 @return 差別

使用方法

  • 以一個分頁列表介面為例
class OrderController extends Controller
{
      public function actionList(Request $request)
    {
            $page = $request->get('page', 1);
            $pageSize = $request->get('size', 10);
            $results = [];
            $list = OrderInfoModel::singleton()->findListByPage($page, $pageSize);
            if ($list) foreach ($list as $item) {
                  $results[] = ['order_sn' => $item->order_sn]; //在IDE中, 這個$item->order_sn是有輔助提示的,就是Model中的@property起的作用
            }
            //其他程式碼省略
      }
}

相關文章