postgres - 使用主键时缓慢的外部查询

时间:2011-11-18 23:37:36

标签: postgresql query-optimization

使用Postgres v.8.4.2。

我有一个标准的三表设置,用于多对多关系。针对其中两个表编写的查询应该返回没有现有映射的单个记录:

SELECT b.id
   FROM scm_branch b
      LEFT OUTER JOIN "scm_branchgroup_branches" bgb
         ON b.id = bgb.branch_id
   WHERE
         bgb.branch_id is NULL
   LIMIT 1

(scm_branchgroup_branches是保存映射记录的三元表)

此查询具有以下顶级费用:

  

限制(成本= 0.00..0.22行= 1宽度= 4)

但是,如果我将WHERE条件中使用的字段更改为bgb表的主键,则成本会急剧上升:

SELECT b.id
   FROM scm_branch b
      LEFT OUTER JOIN "scm_branchgroup_branches" bgb
         ON b.id = bgb.branch_id
   WHERE
         bgb.id IS NULL 
   LIMIT 1

(注意:此查询使用“bgb.id IS NULL”vs“bgb.branch_id is NULL”在前面的示例中使用)

顶级费用:

  

限制(成本= 236366.74..4644900.75行= 1宽度= 4)

为什么会出现如此剧烈的差异?我的意思是我看到了执行计划的差异,但我不明白差异的根本原因。

我很乐意提供回答此问题所需的任何其他信息。

由于 d。

1 个答案:

答案 0 :(得分:1)

branch_id IS NULL的版本中,PostgreSQL认识到您正在进行反连接,并使用“哈希连接”类型算法进行相应的优化。 (Google PostgreSQL hash left anti-join提供了有关此优化的大量信息。)但是,在id IS NULL的版本中,它无法识别这一事实,并且其优化功能并不那么有用。更重要的是,连接基本上强制它使用branch_id上的索引,因此它无法利用id上的主键索引,并且必须参考实际的表数据来确定是否给定记录满足WHERE条款。

(可能还有其他因素在起作用 - 我不是PostgreSQL的专家 - 但我相信这些是主要因素。)