2011-01-14 78 views
1

我在此處發佈了上一個問題,詢問什麼是更好的,JOIN使用子查詢的查詢或查詢。鏈接:Queries within queries: Is there a better way?需要幫助瞭解JOIN查詢與使用子查詢的查詢的SQL解釋

這是對該問題的擴展。有人可以向我解釋爲什麼我看到我在這裏看到的是什麼?

查詢(子選擇):

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多個)

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 S的關係被證明有較好的效果。然而,在我的所有測試中,我看到JOIN s會有幾毫秒的更糟糕的結果。它似乎也像JOIN s充滿了嵌套循環。我所有的表格都是JOIN ing。

我正在做一些我應該採取不同的行動嗎?有什麼我失蹤?

+0

這些表有多少行?子查詢在少量行上可以更快......您是否嘗試10.000行或更多? – 2011-01-14 15:58:11

回答

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返回重複項。

如果沒有typesownerskbreviewskbarticle,第一查詢將在適當的領域返回NULL,而第二個將只是忽略該記錄。

如果*_seq字段似乎是PRIMARY KEY字段,那麼永遠不會有重複,並且查詢永遠不會失敗;以相同的方式,如果kbarticles受到FOREIGN KEY的限制,則參考typesownerskbreview,則不會有缺失的行。

然而,JOIN運營商給予更多優化的地方:它可以使任何表領先,並使用更先進的技術JOINHASH JOINMERGE JOIN其不可用,如果你正在使用子查詢。

+0

所以,基本上你會說我應該堅持`JOIN`s,因爲它們在長期運行中提供了更多的好處,並且真正使幾毫秒可以忽略不計? – 2011-01-14 15:47:31

0

此表格列索引? r.article_seq

- > SEQ掃描上kbreview R(成本= 0.00..14.54行= 1米寬度= 12) (實際時間= 0.267..1.175行= 1個 循環= 1)

這是大部分時間花在哪裏。

+0

是的,該列有索引。 `kbreview_article_seq \t CREATE INDEX kbreview_article_seq ON kbreview USING btree(article_seq)` – 2011-01-14 15:37:53

0

鑑於這兩個計劃都在做同樣的表掃描,只是以不同的方式安排,我會說沒有顯着兩者之間的區別。下臂產生單行的「嵌套循環」與單行子查詢非常相似。

聯接更一般,因爲使用標量子查詢不會擴展到例如從這些輔助表中獲取兩列。