Laravel Model查询结果的3种存储格式内存占用对比

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起的作用
            }
            //其他代码省略
      }
}

你可能感兴趣的:(Laravel Model查询结果的3种存储格式内存占用对比)