优化Django` .exists()`查询

时间:2017-11-09 15:25:10

标签: sql django django-orm

我正在编写的应用中有.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()返回一个布尔值。没有返回的列用于任何事情。它们只会使查询复杂化并降低性能。

1 个答案:

答案 0 :(得分:0)

我发现在我的QuerySet构建期间,.distinct()之前正在调用.exists()。这导致不必要地选择列。