PostgreSQL如何执行查询?

时间:2014-04-22 09:16:02

标签: postgresql

任何人都可以解释为什么PostgreSQL如此运作:

如果我执行此查询

SELECT
*
FROM project_archive_doc as PAD, project_archive_doc as PAD2
WHERE
PAD.id = PAD2.id

这将很简单JOINEXPLAIN将如下所示:

Hash Join  (cost=6.85..13.91 rows=171 width=150)
  Hash Cond: (pad.id = pad2.id)
  ->  Seq Scan on project_archive_doc pad  (cost=0.00..4.71 rows=171 width=75)
  ->  Hash  (cost=4.71..4.71 rows=171 width=75)
        ->  Seq Scan on project_archive_doc pad2  (cost=0.00..4.71 rows=171 width=75)

但如果我将执行此查询:

SELECT *
FROM project_archive_doc as PAD
WHERE
PAD.id = (
          SELECT PAD2.id
          FROM project_archive_doc as PAD2
          WHERE
          PAD2.project_id = PAD.project_id
          ORDER BY PAD2.created_at
          LIMIT 1)

没有联接,EXPLAIN看起来像:

Seq Scan on project_archive_doc pad  (cost=0.00..886.22 rows=1 width=75)"
  Filter: (id = (SubPlan 1))
  SubPlan 1
    ->  Limit  (cost=5.15..5.15 rows=1 width=8)
          ->  Sort  (cost=5.15..5.15 rows=1 width=8)
                Sort Key: pad2.created_at
                ->  Seq Scan on project_archive_doc pad2  (cost=0.00..5.14 rows=1 width=8)
                      Filter: (project_id = pad.project_id)

为什么会这样,是否有关于此的文档或文章?

1 个答案:

答案 0 :(得分:2)

没有表格定义和数据,这种情况很难具体。通常,PostgreSQL与大多数SQL数据库一样,因为它不会将SQL视为如何执行查询的逐步程序。它更像是对结果的描述,以及您希望数据库如何产生这些结果的提示。

PostgreSQL可以自由地实际执行查询,但它可以最有效地执行查询,只要它产生您想要的结果。

通常它有多种关于如何产生特定结果的选择。它将根据成本估算在它们之间进行选择。

它还可以“理解”编写特定查询的几种不同方式是等效的,并将其转换为另一种更有效的方式。例如,它可以将IN (SELECT ...)转换为连接,因为它可以证明它们是等效的。

然而,有时对查询的显然微小变化从根本上改变了它的含义,并限制了PostgreSQL可以进行的优化/转换。在子查询中添加LIMITOFFSET会阻止PostgreSQL从展平它,即通过将其转换为连接将其与外部查询相结合。它还可以防止PostgreSQL在子查询和外部查询之间移动WHERE子句条目,因为这会改变查询的含义。如果没有LIMITOFFSET子句,它可以执行这两项操作,因为它们不会更改查询的含义。

some info on the planner here