2012-03-13 231 views
1

我有一張表,我只插入行,從不刪除。 在每個循環中,我插入大約36k行。在postgres中真的很慢性能

我需要從該表中獲取行來執行操作。 問題出在每個循環上,查詢性能真的很差。

例如,在環31:

explain analyze select exp(least(709,a.value)), a.from, a.to,a.material,a.transport from resultTable a where a.loop=31; 
                      QUERY PLAN 
----------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Bitmap Heap Scan on resultTable a (cost=36.58..4431.79 rows=2425 width=48) (actual time=7.351..33894.217 rows=34640 loops=1) 
    Recheck Cond: (loop = 31) 
    -> Bitmap Index Scan on "resultTable_idx_mo" (cost=0.00..35.97 rows=2425 width=0) (actual time=4.880..4.880 rows=34640 loops=1) 
     Index Cond: (loop = 31) 
Total runtime: 33897.070 ms 
(5 rows) 

對於循環43:

explain analyze select exp(least(709,a.value)), a.from, a.to,a.material,a.transport from resultTable a where a.loop=43; 
                      QUERY PLAN 
----------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Bitmap Heap Scan on resultTable a (cost=36.58..4431.79 rows=2425 width=48) (actual time=10.129..125460.445 rows=34640 loops=1) 
    Recheck Cond: (loop = 43) 
    -> Bitmap Index Scan on "resultTable_idx_mo" (cost=0.00..35.97 rows=2425 width=0) (actual time=4.618..4.618 rows=34640 loops=1) 
     Index Cond: (loop 43) 
Total runtime: 125463.516 ms 
(5 rows) 

的時間被成長爲指數。 我在每個循環中都做了VACUUM和REINDEX(我也試過沒有,但結果是一樣的)。

任何想法如何提高時間?

在此先感謝。

分區後:

QUERY PLAN 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Result (cost=14.47..2686.29 rows=1649 width=48) (actual time=18.562..220124.597 rows=34640 loops=1) 
    -> Append (cost=14.47..2682.17 rows=1649 width=48) (actual time=5.189..32.743 rows=34640 loops=1) 
     -> Bitmap Heap Scan on resultTable a (cost=14.47..1655.44 rows=866 width=48) (actual time=0.008..0.008 rows=0 loops=1) 
       Recheck Cond: (loop = 60) 
       -> Bitmap Index Scan on "resultTable_idx_mo" (cost=0.00..14.26 rows=866 width=0) (actual time=0.006..0.006 rows=0 loops=1) 
        Index Cond: (loop = 60) 
     -> Bitmap Heap Scan on result_table_child_70 a (cost=8.82..1026.73 rows=783 width=48) (actual time=5.181..29.068 rows=34640 loops=1) 
       Recheck Cond: (loop = 60) 
       -> Bitmap Index Scan on resultTable_child_70_idx (cost=0.00..8.63 rows=783 width=0) (actual time=4.843..4.843 rows=34640 loops=1) 
        Index Cond: (loop = 60) 
Total runtime: 220128.290 ms 

分析表後和設置enable_bitmapscan = OFF(仍然使用分區):

Result (cost=0.00..2761.06 rows=33652 width=389) (actual time=9.714..378389.177 rows=34640 loops=1) 
    -> Append (cost=0.00..2676.93 rows=33652 width=389) (actual time=0.119..34.065 rows=34640 loops=1) 
     -> Index Scan using "resultTable_idx_mo" on resultTable a (cost=0.00..12.84 rows=5 width=48) (actual time=0.058..0.058 rows=0 loops=1) 
       Index Cond: (loop= 79) 
     -> Index Scan using resultTable_child_80_idx on resultTable_child_80 a (cost=0.00..2664.10 rows=33647 width=389) (actual time=0.061..30.303 rows=34640 loops=1) 
       Index Cond: (loop = 79) 
Total runtime: 378393.671 ms 
(7 rows) 

回答

4

如果集羣和分區不工作,我開始懷疑你有你的存儲系統的一些嚴重的問題。十幾秒鐘的時間堆積掃描35K行是幾個數量級太慢。你使用的是什麼版本的Postgres?你的存儲是什麼樣的?檢查你的iostats。

我使用Pg 9.0.4爲小型虛擬機(1小數CPU,1GB內存,NFS磁盤安裝)設置了一個實驗,讓您的表和索引以及每批註入1000個批次的36000條記錄。

insert into r(loop,value,xfrom,xto,material,transport,pk) select 0,0,0,0,0,0,i from generate_series(0,35999) i; 
insert into r(loop,value,xfrom,xto,material,transport,pk) select 1,0,0,0,0,0,i from generate_series(36000,71999) i; 
... 

運行你選擇的任何批次始終爲40ms下:

explain analyze select exp(least(709,a.value)), a.xfrom, a.xto, a.material,a.transport from r a where a.loop=31; 
Index Scan using "resultTable_idx_mo" on r a (cost=0.00..1596.35 rows=37680 width=21) (actual time=0.087..34.038 rows=36000 loops=1) 
    Index Cond: (loop = 31) 
Total runtime: 36.332 ms 

explain analyze select exp(least(709,a.value)), a.xfrom, a.xto,a.material,a.transport from r a where a.loop=87; 
Index Scan using "resultTable_idx_mo" on r a (cost=0.00..1421.35 rows=33480 width=21) (actual time=0.105..37.357 rows=36000 loops=1) 
    Index Cond: (loop = 87) 
Total runtime: 39.365 ms 

注意我的計劃拿出普通IndexScan的,而不是BitmapScans其次HeapScans。你有沒有調整計劃優化配置來影響計劃?

在你的解釋中,我注意到估計的行數遠遠小於實際的行數(1649 vs 34640)。這表明你在表格上有不準確的統計數據。你應該運行ANAYLZE resultTable;

我相信當你的postgres配置或者你的存儲系統出現這種簡單的索引掃描選擇需要超過幾十毫秒的時候,會出現一些糟糕的事情。當你運行你的查詢時,這個數據庫還有其他的活動嗎?也許你的結果是與其他查詢競爭資源?

+0

我更新了底部的帖子(使用循環79)。謝謝 – baboso 2012-03-14 10:04:37

+0

如果你連續運行兩次相同循環值的解釋分析,運行時間會顯着提高嗎? 36K * 48bytes的行寬大約是2MB。一旦pg已經讀取了所有的數據塊,它們應該很容易適應並保留在任何合理大小的系統上的OS頁面緩存中,所以在第二次運行時,堆掃描應該完全收集沒有IO的內存行。你的系統有多少內存? – dbenhur 2012-03-14 15:17:03