2013-04-30 115 views
0
vit=# select count(*) from evtags; 
    count 
--------- 
4496914 

vit=# explain select tag from evtags where evid in (1002, 1023); 
           QUERY PLAN          
--------------------------------------------------------------------------------- 
Index Only Scan using evtags_pkey on evtags (cost=0.00..15.64 rows=12 width=7) 
    Index Cond: (evid = ANY ('{1002,1023}'::integer[])) 

到目前爲止,這看起來完全沒問題。接下來,我想使用另一個表中的ID而不是在查詢中指定它們。選擇包含在另一個表中的ID的記錄

vit=# select count(*) from zzz; 
count 
------- 
49738 

在這裏,我們去...

vit=# explain select tag from evtags where evid in (select evid from zzz); 
           QUERY PLAN        
----------------------------------------------------------------------- 
Hash Semi Join (cost=1535.11..142452.47 rows=291712 width=7) 
    Hash Cond: (evtags.evid = zzz.evid) 
    -> Seq Scan on evtags (cost=0.00..69283.14 rows=4496914 width=11) 
    -> Hash (cost=718.38..718.38 rows=49738 width=4) 
     -> Seq Scan on zzz (cost=0.00..718.38 rows=49738 width=4) 

爲什麼在更多更大的表索引掃描,什麼是應該做的正確方法?

編輯

我重新創建我的zzz表,現在它是由於某種原因,更好:

vit=# explain analyze select tag from evtags where evid in (select evid from zzz); 
                 QUERY PLAN                
------------------------------------------------------------------------------------------------------------------------------------ 
Nested Loop (cost=708.00..2699.17 rows=2248457 width=7) (actual time=28.935..805.923 rows=244353 loops=1) 
    -> HashAggregate (cost=708.00..710.00 rows=200 width=4) (actual time=28.893..54.461 rows=38822 loops=1) 
     -> Seq Scan on zzz (cost=0.00..601.80 rows=42480 width=4) (actual time=0.032..10.985 rows=40000 loops=1) 
    -> Index Only Scan using evtags_pkey on evtags (cost=0.00..9.89 rows=6 width=11) (actual time=0.015..0.017 rows=6 loops=38822) 
     Index Cond: (evid = zzz.evid) 
     Heap Fetches: 0 
Total runtime: 825.651 ms 

但幾經執行它改變

vit=# explain analyze select tag from evtags where evid in (select evid from zzz); 
                    QUERY PLAN                  
--------------------------------------------------------------------------------------------------------------------------------------------------- 
Merge Semi Join (cost=4184.11..127258.48 rows=235512 width=7) (actual time=38.269..1461.755 rows=244353 loops=1) 
    Merge Cond: (evtags.evid = zzz.evid) 
    -> Index Only Scan using evtags_pkey on evtags (cost=0.00..136736.89 rows=4496914 width=11) (actual time=0.038..899.647 rows=3630070 loops=1) 
     Heap Fetches: 0 
    -> Materialize (cost=4184.04..4384.04 rows=40000 width=4) (actual time=38.212..61.038 rows=40000 loops=1) 
     -> Sort (cost=4184.04..4284.04 rows=40000 width=4) (actual time=38.208..51.104 rows=40000 loops=1) 
       Sort Key: zzz.evid 
       Sort Method: external sort Disk: 552kB 
       -> Seq Scan on zzz (cost=0.00..577.00 rows=40000 width=4) (actual time=0.018..8.833 rows=40000 loops=1) 
Total runtime: 1484.293 ms 

...這實際上是較慢的。有什麼方法可以暗示它是一個「正確的」執行計劃嗎?

這些操作的要點是,我想對我的數據的一個子集執行大量查詢,並希望使用單獨的臨時表來保存要處理的記錄的ID。

+0

做你的表有主/外鍵(沒有索引掃描,可能有兩個)你有有效的統計數據嗎?請添加表格定義,包括PK/FK和/或索引。順便說一句:如果結果集很小並且大部分元組都是需要的,這種計劃是正常的。 BTW2:'解析分析'會顯示*估計和測量的計數/數字。 – wildplasser 2013-04-30 09:46:39

+0

更新了我的問題。 – mifki 2013-04-30 10:11:15

+1

您是否重新創建'zzz'表後運行'vacuum analyze'? (它會更新統計信息)另外:「外」表需要大約50%的行,索引可能無助於找到它們(因爲基本上每個磁盤頁面都將被需要)。你可以嘗試將random_page_cost降低到1.5(或work_mem爲更小的值)來強制執行索引掃描,但只有當需要獲取更少的行/頁時纔有意義。 BTW:zzz表有PK/FK /索引嗎? **請添加表格定義**,包括PK/FK /索引。 – wildplasser 2013-04-30 10:25:19

回答

1

內連接有一個很好的計劃更好的機會:

select e.tag 
from 
    evtags e 
    inner join 
    zzz z using (evid) 

或者這樣:

select e.tag 
from evtags e 
where exists (
    select 1 
    from zzz 
    where evid = e.evid 
) 

正如在評論中指出運行analyze evtags; analyze zzz;

相關問題