【问题标题】:Optimizing a Django `.exists()` query优化 Django `.exists()` 查询
【发布时间】:2018-04-22 16:00:00
【问题描述】:

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

【问题讨论】:

  • 您使用的是什么版本的 Django,以及导致该查询的代码是什么?当我尝试User.objects.exists() 时,它会运行SELECT (1) AS "a" FROM "auth_user" LIMIT 1,这是我所期望的。
  • 我使用的是 Django 1.11.5。我会环顾四周,看看是否有任何自定义代码干扰了这一点并导致选择了额外的列。
  • 在我不知道的地方有一个 .distinct() 调用应用于我的 QuerySet。这把一切都搞砸了。

标签: sql django django-orm


【解决方案1】:

我发现在我的 QuerySet 构建过程中,.distinct() 在我的 .exists() 之前被调用。它导致不必要地选择列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 2011-10-08
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多