暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

odoo优化案例三

Odoo哥 2021-11-19
552

上一篇文章讲到了在domain中使用one2many字段时生成了复杂的SQL语句,今天我们再来看一个使用many2one字段生成的SQL。

首先还是把相关的数据模型定义交待一下:

model A:

    name:姓名(char)

    project:体检项目(char)

    sex:性别(selection)

    

model B:

    parent_id:父记录(many2one,model_A)

    state:状态(selection)


这两个数据模型,A是个人信息,B是体检结果。在原来的业务中,model B有一个方法中使用了search,其中domain是这样写的:

 self.search([("state","=","done"),
        ("parent_id.project","=",u"甲状腺癌"),
("parent_id.sex","=","M")],order="id desc",limit=1)

这个查询看起来比较简单,就是找一笔(limit=1)最新的(id desc)相同体检项目和性别的其他人的体检结果。

后来在查看PG日志的时候,发现了这一笔查询比较慢,将近需要3秒的时间,追踪了一下ORM生成的SQL语句,大致是这样子的:

SELECT "model_B".id 
FROM "model_B"
WHERE ((("model_B"."state" = 'done')
AND ("model_B"."parent_id" in (/*大量id 1*/)))
AND ("model_B"."parent_id" in (/*大量id 2*/)))
ORDER BY "model_B"."id" DESC limit 1

这个查询语句没有使用到model A,但出现了两个parent_id in (大量id)的情况,估计跟domain中的parent_id.project和parent_id.sex有关。

继续追踪了一下odoo中SQL记录,果然在执行这个domain的时候,odoo在后台另外生成了两笔SQL:

select distinct(idfrom model_A where project='甲状腺癌'
select distinct(id) from model_A where sex='M'

然后odoo把这两笔sql查询得到的id值分别带入了前面一条的in条件中。因为在model_A中,数据很多,根据项目或性别去查询的话,随便就是几万笔记录。

因为这个查询条件单独在model A和model B中都会有许多记录,而关联后只要取最新的一笔,这个直接用ORM好像还不好优化。所以我们直接改用了原始的SQL查询:

select a.id 
from model_B a
join model_A b on b.id=a.parent_id 
where b.project='甲状腺癌' and b.sex='M' 
and a.state='done' order by a.id desc limit 1

这样SQL的执行计划就快多了。

文章转载自Odoo哥,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论