activerecord对象内存是数组的3倍,因其含属性映射、状态管理、事件监听及对象头等开销;asarray适用于只读导出、api返回、统计聚合;需模型能力时应select精简字段、禁用自动关联、分批迭代并手动释放。

Yii2 中查询 1000 条记录时,asArray() 返回二维数组约占用 4MB 内存,而默认返回 ActiveRecord 对象则高达约 12MB —— 差了近 3 倍。这并非异常,而是由对象模型的固有开销决定的。
为什么对象内存是数组的 3 倍?
ActiveRecord 实例不只是数据容器,每个对象都包含:
- 完整的属性映射(包括未查询字段的 null 占位)
- 内部状态管理(
$_oldAttributes、$_related、$_errors等私有属性) - 事件监听器绑定(即使没显式注册,基类也预留了空间)
- 类元信息和 PHP 对象头开销(每个对象额外 ~200–300 字节)
什么场景该坚持用 asArray?
当只需读取、格式化或导出数据,不涉及业务逻辑、验证、保存或关联操作时,asArray() 是更优选择:
- 后台列表页分页渲染(尤其带导出 Excel / CSV)
- API 接口返回原始数据(配合
Json::encode()) - 批量统计、聚合计算(如
sum()、count()后再查详情)
想保留对象能力又降内存?试试这些
若必须用 ActiveRecord(比如要调用 beforeSave 或访问关联),可主动控制膨胀点:
- 用
select()明确指定字段,避免*带入冗余列 - 关闭自动关系加载:
with([])或查完再按需loadWith() - 大结果集改用
each()或batch()迭代,避免全量驻留内存 - 必要时手动
unset($model)或置为null,促 GC 回收
对象与数组不是非此即彼,关键是根据数据流向选对抽象层级。查千条只展示?asArray 足够快也足够轻。要复用模型行为?那就接受合理开销,并通过精简字段和分批处理来平衡。











