我正在编写的应用中有.exists()
个查询。我想优化它。
当前的ORM表达式产生如下所示的SQL:
SELECT DISTINCT
(1) AS "a",
"the_model"."id",
... snip every single column on the_model
FROM "the_model"
WHERE (
...snip criteria...
LIMIT 1
解释计划如下:
Limit (cost=176.60..176.63 rows=1 width=223)
-> Unique (cost=176.60..177.40 rows=29 width=223)
-> Sort (cost=176.60..176.67 rows=29 width=223)
Sort Key: id, ...SNIP...
-> Index Scan using ...SNIP... on ...SNIP... (cost=0.43..175.89 rows=29 width=223)
Index Cond: (user_id = 6)
Filter: ...SNIP...
如果我手动修改上面的SQL并删除单个表列,那么它看起来像这样:
SELECT DISTINCT
(1) AS "a",
FROM "the_model"
WHERE (
...snip criteria...
LIMIT 1
解释计划显示了更少的步骤,这很棒。
Limit (cost=0.43..175.89 rows=1 width=4)
-> Unique (cost=0.43..175.89 rows=1 width=4)
-> Index Scan using ...SNIP... on ...SNIP... (cost=0.43..175.89 rows=29 width=4)
Index Cond: (user_id = 6)
Filter: ...SNIP...
我可以从查询中删除DISTINCT
关键字,从而产生更浅的执行计划,尽管这里的成本节省很小:
Limit (cost=0.43..6.48 rows=1 width=4)
-> Index Scan using ..SNIP... on ..SNIP... (cost=0.43..175.89 rows=29 width=4)
Index Cond: (user_id = 6)
Filter: ..SNIP...
我可以使用.only('id')
修改ORM表达式,只选择一个字段。但是,这不会产生我想要的结果。它正在对id
进行不必要的排序。理想情况下,我想做一个.only(None)
,因为这里不需要任何列。它们只会增加重量。
如果可能,我还想删除DISTINCT
关键字。如果删除列,我认为它不会增加太多执行时间。
似乎这可以全面完成,因为.exists()
返回一个布尔值。没有返回的列用于任何事情。它们只会使查询复杂化并降低性能。
答案 0 :(得分:0)
我发现在我的QuerySet构建期间,.distinct()
之前正在调用.exists()
。这导致不必要地选择列。