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

  • 2020 年 9 月 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起的作用
            }
            //其他程式碼省略
      }
}