需要帮助理解JOIN查询的SQL解释与带有子选择的查询

时间:2011-01-14 15:27:34

标签: sql postgresql join query-optimization subquery

我在此处发布了一个问题,询问使用子选择的更好,JOIN查询或查询。链接:Queries within queries: Is there a better way?

这是该问题的扩展。有人可以向我解释为什么我看到我在这里看到的东西吗?

查询(子选择):

SELECT article_seq, title, synopsis, body, lastmodified_date, (SELECT type_id FROM types WHERE kbarticles.type = type_seq), status, scope, images, archived, author, owner, (SELECT owner_description FROM owners WHERE kbarticles.owner = owner_seq),  (SELECT review_date FROM kbreview WHERE kbarticles.article_seq = article_seq) FROM kbarticles WHERE article_seq = $1

解释分析(子选择)

QUERY PLAN

Index Scan using article_seq_pkey on kbarticles  (cost=0.00..32.24 rows=1 width=1241) (actual time=1.421..1.426 rows=1 loops=1)

  Index Cond: (article_seq = 1511)

  SubPlan

    ->  Seq Scan on kbreview  (cost=0.00..14.54 rows=1 width=8) (actual time=0.243..1.158 rows=1 loops=1)

          Filter: ($2 = article_seq)

    ->  Seq Scan on owners  (cost=0.00..1.16 rows=1 width=24) (actual time=0.073..0.078 rows=1 loops=1)

          Filter: ($1 = owner_seq)

    ->  Index Scan using types_type_seq_key on types  (cost=0.00..8.27 rows=1 width=24) (actual time=0.044..0.050 rows=1 loops=1)

          Index Cond: ($0 = type_seq)

Total runtime: 2.051 ms

查询(JOIN s)

SELECT k.article_seq, k.title, k.synopsis, k.body, k.lastmodified_date, t.type_id, k.status, k.scope, k.images, k.archived, k.author, k.owner, o.owner_description, r.review_date FROM kbarticles k JOIN types t ON k.type = t.type_seq JOIN owners o ON k.owner = o.owner_seq JOIN kbreview r ON k.article_seq = r.article_seq WHERE k.article_seq = $1

解释分析(JOIN s)

QUERY PLAN

Nested Loop  (cost=0.00..32.39 rows=1 width=1293) (actual time=0.532..1.467 rows=1 loops=1)

  Join Filter: (k.owner = o.owner_seq)

  ->  Nested Loop  (cost=0.00..31.10 rows=1 width=1269) (actual time=0.419..1.345 rows=1 loops=1)

        ->  Nested Loop  (cost=0.00..22.82 rows=1 width=1249) (actual time=0.361..1.277 rows=1 loops=1)

              ->  Index Scan using article_seq_pkey on kbarticles k  (cost=0.00..8.27 rows=1 width=1241) (actual time=0.065..0.071 rows=1 loops=1)

                    Index Cond: (article_seq = 1511)

              ->  Seq Scan on kbreview r  (cost=0.00..14.54 rows=1 width=12) (actual time=0.267..1.175 rows=1 loops=1)

                    Filter: (r.article_seq = 1511)

        ->  Index Scan using types_type_seq_key on types t  (cost=0.00..8.27 rows=1 width=28) (actual time=0.048..0.055 rows=1 loops=1)

              Index Cond: (t.type_seq = k.type)

  ->  Seq Scan on owners o  (cost=0.00..1.13 rows=13 width=28) (actual time=0.022..0.038 rows=13 loops=1)

Total runtime: 2.256 ms

根据我在上一个问题中给出(并接受)的答案,JOIN应该证明有更好的结果。但是,在我的所有测试中,我都看到JOIN的结果差几毫秒。似乎JOIN s充满了嵌套循环。我JOIN的所有表都被编入索引。

我做的事情我应该采取不同的做法吗?有什么我想念的吗?

3 个答案:

答案 0 :(得分:2)

这些查询在逻辑上是不同的。

第一个:

SELECT  article_seq, title, synopsis, body, lastmodified_date,
        (
        SELECT  type_id
        FROM    types
        WHERE   kbarticles.type = type_seq
        ),
        status, scope, images, archived, author, owner,
        (
        SELECT  owner_description
        FROM    owners
        WHERE   kbarticles.owner = owner_seq
        ),
        (
        SELECT  review_date
        FROM    kbreview
        WHERE   kbarticles.article_seq = article_seq
        )
FROM    kbarticles
WHERE   article_seq = $1

第二个:

SELECT  k.article_seq, k.title, k.synopsis, k.body, k.lastmodified_date, t.type_id, k.status,
        k.scope, k.images, k.archived, k.author, k.owner, o.owner_description, r.review_date
FROM    kbarticles k
JOIN    types t
ON      k.type = t.type_seq
JOIN    owners o
ON      k.owner = o.owner_seq
JOIN    kbreview r
ON      k.article_seq = r.article_seq
WHERE   k.article_seq = $1

如果typesownerskbreview中有多条记录,则第一个查询将失败,而第二个查询将从kbarticles返回重复项。

如果types没有ownerskbreviewskbarticle,则第一个查询将在相应字段中返回NULL,而第二个查询将返回*_seq一个人将省略该记录。

如果PRIMARY KEY字段似乎是kbarticles字段,则永远不会有重复项,并且查询永远不会失败;如果FOREIGN KEYtypes ownerskbreviewJOIN的{​​{1}}引用限制,则同样如此,也不会有丢失的行。

但是,JOIN运算符可为优化程序提供更多位置:它可以使任何表格领先,并使用更高级的HASH JOIN技术,如MERGE JOIN或{{1}},如果不可用你正在使用子查询。

答案 1 :(得分:0)

此表格列是否已编入索引? r.article_seq

  

- >在kbreview r上进行Seq Scan(成本= 0.00..14.54行= 1宽度= 12)   (实际时间= 0.267..1.175行= 1   循环= 1)

这是花费大部分时间的地方。

答案 2 :(得分:0)

鉴于两个计划都在进行相同的表扫描,只是以不同的方式排列,我会说两者之间没有显着的差异。下臂产生单行的“嵌套循环”与单行子选择几乎相同。

连接更通用,因为使用标量子选择不会扩展到从任何辅助表中获取两列,例如。