ORM 性能

Odoo 为什么总强调批量写法:recordset、prefetch、批处理 ORM 背后的性能逻辑

很多 Odoo 性能问题,不是数据库本身太慢,而是代码总在单条循环里把 ORM 优势用没了。本文讲清 recordset 和 prefetch 背后的思路。

Odoo 开发
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 6 阅读

先说结论

Odoo 一直鼓励你用 recordset 和批量思维写代码,不是为了代码看起来“更 Odoo”,而是因为 ORM 的性能机制本来就是围绕批量优化设计的。

这背后最关键的两个概念通常就是:

  • recordset
  • prefetch

你只要理解它们,很多“为什么官方源码老不按单条写”的问题就通了。


为什么新手总喜欢按单条记录思维写

因为这最符合直觉。

很多人自然会写成:

  • 拿一条记录
  • 查一点字段
  • 处理一下
  • 再拿下一条

这在少量数据时看起来没问题。

但一旦数据量上来,这种写法很容易变成:

  • 查询很多次
  • 重复读很多字段
  • 循环里不断触发 ORM 开销

最后你会感觉 Odoo 很慢,实际上很多时候是写法把 ORM 的批量优势浪费掉了。


recordset 为什么这么核心

因为 Odoo 的很多 API 天然就是按“一批记录”来思考的,而不是按“当前这一条”来思考。

这意味着:

  • self 经常本来就可能是多条
  • 你可以对整批记录一起过滤、映射、写入
  • ORM 也更容易在这个层面做优化

所以 recordset 不是“好像有点高级的集合对象”,它是 Odoo 代码风格的基本单位。


prefetch 本质上在帮你做什么

最通俗地说,prefetch 在做的是:

既然你已经在处理这批记录了,那相关字段我尽量一起读,别你每碰一次都单独查。

这就是为什么批量拿记录、再按字段访问时,性能通常会比你一条条零碎处理更稳。

因为 ORM 会尽量把“这批记录大概率会用到的数据”提前组织得更高效。


为什么循环里乱访问关系字段特别容易慢

因为每次你在循环里继续追关联对象、再拿关联字段,如果写法不稳,就很容易不断触发额外查询。

典型现象是:

  • 外层循环产品
  • 内层去读供应商
  • 再去读公司
  • 再去读分类

逻辑上很顺,性能上却可能层层放大。

所以 Odoo 性能优化里,一个特别重要的习惯就是:

先用批量思维把要用的数据范围组织好,再做业务处理。


为什么官方源码经常喜欢“先收集、再统一处理”

因为这样更符合 ORM 优势。

你会经常看到类似套路:

  • 先筛出一批记录
  • 先 map 出一批关联对象
  • 先 regroup / 分组
  • 再统一 create / write / confirm

这不是写法绕,而是因为一旦流程走到批量层,ORM、缓存和数据库都更容易协同优化。


什么叫“不要总按单条记录思维写”

不是说单条永远不行。

而是说你应该先问自己:

  • 这段逻辑是不是本来就面对一批记录
  • 我是不是在循环里重复做相同查询
  • 我能不能先把相关数据批量拿出来
  • 我能不能把 write / create 合并成批操作

只要这些问题开始出现,说明你已经该从“单条脑回路”切到“recordset 脑回路”了。


实战里最容易踩的 5 个坑

1. 方法天然支持多记录,却默认按一条写

很容易丢掉批量优势。

2. 循环里频繁 search / browse / 追关系

性能最容易炸在这里。

3. 可以一次 write,却拆成很多次写

数据库和 ORM 开销都会放大。

4. 不理解 prefetch,就误以为“访问字段很便宜”

字段访问不是总无成本的。

5. 只在小数据量下测试

上线后才暴露慢的问题。


一句话记忆法

把这套机制记成一句话:

recordset 是 Odoo 处理业务对象的基本批量单位,prefetch 是 ORM 为这批对象提前组织数据的性能机制,所以很多代码都应该先按“整批记录”思考,而不是一条条硬循环。

理解这一句,很多 Odoo ORM 性能问题都会顺很多。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。