0
它看起來像從執行計劃的版本快於EXISTS版本如何解釋這個執行計劃(IN vs EXISTS)?
我想存在的查詢速度更快,因爲它急切地檢查的條件。 IN查詢雖然看起來很直觀,但我覺得它似乎很晚就解決了最終條件的結果;即從內向外,我發現IN較慢,因爲下一個條件需要等待的內部條件的結果。
雖然從下面的執行計劃看,IN更快;它具有較低的成本。
我的一部分想要使用IN版本,它對於下一個維護者來說看起來簡單直觀,下面的執行計劃似乎表明它比EXISTS更快。但我的另一部分人想要使用EXISTS,因爲我覺得它更快,但下面的執行計劃似乎與這種看法相矛盾。
下面兩個查詢中哪個更快,是IN版本還是EXISTS版本?
版本:
explain analyze
select ceil(
(count(distinct company_rec_id)::numeric + 1)
/((1)))::int
from
parcel ord
join company c on c.company_rec_id = ord.client_rec_id
where
(
(((E'')) <> '' and to_tsvector(c.company) @@ plainto_tsquery(extract_words(((E'')))))
or ((E'')) = ''
)
and
(
(((0)) <> 0 and ord.parcel_number = ((0)))
or ((0)) = 0
)
and parcel_rec_id in
(
select parcel_rec_id
from parcel_application
where parcel_application_rec_id in
(
select parcel_application_rec_id
from parcel_application_shoe
where
(
(((E'')) <> '' and to_tsvector(extract_words(shoe_description)) @@ plainto_tsquery(extract_words(((E'')))))
or ((E'')) = ''
)
and
(
(((E'')) <> '' and to_tsvector(extract_words(order_number)) @@ plainto_tsquery(extract_words(((E'')))))
or ((E'')) = ''
)
and
(
(((E'')) <> '' and to_tsvector(extract_words(style_number)) @@ plainto_tsquery(extract_words(((E'')))))
or ((E'')) = ''
)
)
)
"Aggregate (cost=1060.73..1060.75 rows=1 width=37) (actual time=29.028..29.028 rows=1 loops=1)"
" -> Hash Join (cost=880.43..1053.04 rows=3074 width=37) (actual time=13.261..16.365 rows=3074 loops=1)"
" Hash Cond: ((ord.client_rec_id)::text = (c.company_rec_id)::text)"
" -> Hash Join (cost=864.79..995.14 rows=3074 width=37) (actual time=13.115..15.027 rows=3074 loops=1)"
" Hash Cond: ((ord.parcel_rec_id)::text = (parcel_application.parcel_rec_id)::text)"
" -> Seq Scan on parcel ord (cost=0.00..78.87 rows=3087 width=74) (actual time=0.005..0.373 rows=3087 loops=1)"
" -> Hash (cost=826.37..826.37 rows=3074 width=37) (actual time=13.102..13.102 rows=3074 loops=1)"
" -> HashAggregate (cost=795.63..826.37 rows=3074 width=37) (actual time=11.835..12.281 rows=3074 loops=1)"
" -> Hash Join (cost=541.34..787.59 rows=3218 width=37) (actual time=7.076..10.286 rows=3218 loops=1)"
" Hash Cond: ((parcel_application.parcel_application_rec_id)::text = (parcel_application_shoe.parcel_application_rec_id)::text)"
" -> Seq Scan on parcel_application (cost=0.00..122.18 rows=3218 width=74) (actual time=0.004..0.710 rows=3218 loops=1)"
" -> Hash (cost=501.12..501.12 rows=3218 width=37) (actual time=7.061..7.061 rows=3218 loops=1)"
" -> HashAggregate (cost=468.94..501.12 rows=3218 width=37) (actual time=5.721..6.220 rows=3218 loops=1)"
" -> Seq Scan on parcel_application_shoe (cost=0.00..442.95 rows=10395 width=37) (actual time=0.004..2.318 rows=10395 loops=1)"
" -> Hash (cost=11.95..11.95 rows=295 width=37) (actual time=0.136..0.136 rows=295 loops=1)"
" -> Seq Scan on company c (cost=0.00..11.95 rows=295 width=37) (actual time=0.013..0.068 rows=295 loops=1)"
"Total runtime: 29.122 ms"
EXISTS版本:
explain analyze
select ceil(
(count(distinct company_rec_id)::numeric + 1)
/((1)))::int from
parcel ord
join company c on c.company_rec_id = ord.client_rec_id
where
(
(((E'')) <> '' and to_tsvector(c.company) @@ plainto_tsquery(extract_words(((E'')))))
or ((E'')) = ''
)
and
(
(((0)) <> 0 and ord.parcel_number = ((0)))
or ((0)) = 0
)
and exists
(
select * from parcel_application pa
where pa.parcel_rec_id = ord.parcel_rec_id
and
exists
(
select * from parcel_application_shoe ord_item
where
ord_item.parcel_application_rec_id = pa.parcel_application_rec_id
and
(
(((E'')) <> '' and to_tsvector(extract_words(ord_item.shoe_description)) @@ plainto_tsquery(extract_words(((E'')))))
or ((E'')) = ''
)
and
(
(((E'')) <> '' and to_tsvector(extract_words(ord_item.order_number)) @@ plainto_tsquery(extract_words(((E'')))))
or ((E'')) = ''
)
and
(
(((E'')) <> '' and to_tsvector(extract_words(ord_item.style_number)) @@ plainto_tsquery(extract_words(((E'')))))
or ((E'')) = ''
)
)
)
"Aggregate (cost=17773.13..17773.16 rows=1 width=37) (actual time=34.519..34.520 rows=1 loops=1)"
" -> Hash Join (cost=17636.59..17769.11 rows=1609 width=37) (actual time=17.174..20.426 rows=3074 loops=1)"
" Hash Cond: ((ord.client_rec_id)::text = (c.company_rec_id)::text)"
" -> Hash Join (cost=17620.95..17731.35 rows=1609 width=37) (actual time=16.882..18.862 rows=3074 loops=1)"
" Hash Cond: ((ord.parcel_rec_id)::text = (pa.parcel_rec_id)::text)"
" -> Seq Scan on parcel ord (cost=0.00..78.87 rows=3087 width=74) (actual time=0.006..0.409 rows=3087 loops=1)"
" -> Hash (cost=17601.74..17601.74 rows=1537 width=37) (actual time=16.858..16.858 rows=3074 loops=1)"
" -> HashAggregate (cost=17586.37..17601.74 rows=1537 width=37) (actual time=15.015..15.535 rows=3074 loops=1)"
" -> Seq Scan on parcel_application pa (cost=0.00..17582.35 rows=1609 width=37) (actual time=10.040..12.440 rows=3218 loops=1)"
" Filter: (alternatives: SubPlan 1 or hashed SubPlan 2)"
" SubPlan 1"
" -> Index Scan using fki_parcel_application_shoe__parcel_application on parcel_application_shoe ord_item (cost=0.00..16.28 rows=3 width=0) (never executed)"
" Index Cond: ((parcel_application_rec_id)::text = ($0)::text)"
" SubPlan 2"
" -> Seq Scan on parcel_application_shoe ord_item (cost=0.00..442.95 rows=10395 width=37) (actual time=0.005..4.482 rows=10395 loops=1)"
" -> Hash (cost=11.95..11.95 rows=295 width=37) (actual time=0.284..0.284 rows=295 loops=1)"
" -> Seq Scan on company c (cost=0.00..11.95 rows=295 width=37) (actual time=0.010..0.155 rows=295 loops=1)"
"Total runtime: 34.645 ms"
這是最終的查詢我最終使用時,IN版本。我只能看到 IN和EXISTS版本之間的邊際性能差異。我想詳細瞭解可讀性下一個維護者,所以我用IN
select ord.parcel_number, ord.received_date, c.company
from parcel ord
join company c on c.company_rec_id = ord.client_rec_id
where
(
:_company = ''
or
to_tsvector(c.company) @@ plainto_tsquery(extract_words(:_company))
)
and
(
:_fttsc_num = 0
or ord.parcel_number = :_fttsc_num
)
and
(
(:_item = '' and :_order_num = '' and :_style_num = '')
or
ord.parcel_rec_id in
(
select parcel_rec_id
from parcel_application
where parcel_application_rec_id in
(
select parcel_application_rec_id
from parcel_application_shoe
where
(
:_item = ''
or to_tsvector(extract_words(shoe_description)) @@ plainto_tsquery(extract_words(:_item))
)
and
(
:_order_num = ''
or to_tsvector(extract_words(order_number)) @@ plainto_tsquery(extract_words(:_order_num))
)
and
(
:_style_num = ''
or to_tsvector(extract_words(style_number)) @@ plainto_tsquery(extract_words(:_style_num))
)
) -- parcel_application_rec_id IN
) -- parcel_rec_id IN
)
and
-- material filter...
(
(:_material = '')
or
-- implied material <> ''
parcel_rec_id in
(
select parcel_rec_id
from parcel_application
where parcel_application_rec_id in
(
select parcel_application_rec_id
from mlist
where mlist_rec_id in
(
select mlist_rec_id
from mlist_detail
join material m using(material_rec_id)
where to_tsvector(extract_words(m.material)) @@ plainto_tsquery(extract_words(:_material))
)
)
)
)
-- ...material filter
and
-- parameter filter...
(
(:_parameter = '')
or
-- implied parameter <> ''
parcel_rec_id in
(
select parcel_rec_id
from parcel_application
where parcel_application_rec_id in
(
select parcel_application_rec_id
from mlist
where mlist_rec_id in
(
select mlist_rec_id
from mlist_detail
where mlist_detail_rec_id in
(
select mlist_detail_rec_id
from mlist_detail_parameter
join parameter p using(parameter_rec_id)
where to_tsvector(extract_words(p.parameter)) @@ plainto_tsquery(extract_words(:_parameter))
)
)
)
)
)
-- ...parameter filter
order by ord.received_date
你可以添加的EXPLAIN分析的結果? – 2010-07-02 07:23:41
@Frank Heikens:很難獲得總運行時間,他們總是起伏不大,差別不大。但EXISTS似乎更快,每次運行10次,EXISTS進行5次的時間少於30毫秒;而與IN,只有一次 – 2010-07-02 08:18:27
我沒有要求的運行時間,但執行計劃。我假設你之前做過VACUUM ANALYZE,只要確保統計數據是最新的。 – 2010-07-02 08:31:01