2009-11-03 144 views
0

我的任務是提高緩慢運行進程的性能,該進程更新PostGres 8.3數據庫(在Solaris上運行,更新由Perl 5.8腳本通過SOAP驅動)中的一些數據。大約50%的時間消耗我很少控制,所以調整我的50%是非常重要的。性能優化 - Postgres

表中通常有大約4,500,000行,儘管我已經看到它膨脹到約700萬。更新查詢的ID(不是主要的或唯一的)具有近9000個不同的值,並且事件的傳播對每個ID大量加權(中值爲20,最大值爲7000)。

這個ID有一個索引,但有這樣稀疏的數據我不知道是否有更好的方法做事情。我也在考慮對數據進行非規範化處理(無論如何,數據庫並沒有超標準化)&將數據拉出到單獨的表格中(可能由觸發器控制/維護)以幫助加快速度。

到目前爲止,我已經做了一些非常基本的調整(不是每n秒鐘ping數據庫以查看它是否存在,不會不必要地設置會話變量等),這是有幫助的,但我真的覺得有些東西我缺少與數據...

即使有人說,拉出相關數據到一個單獨的表是一個很好的/可怕的想法,這將是非常有益的!任何其他想法(或進一步的澄清問題)感激地收到!

查詢:

UPDATE tab1 SET client = 'abcd', invoice = 999 
    WHERE id = 'A1000062' and releasetime < '02-11-09'::DATE 
    AND charge IS NOT NULL AND invoice IS NULL AND client IS NULL; 

我意識到 '不爲空' 是遠遠不夠理想。編號索引,發票&客戶端(btrees,所以我明白PostGres將/應該/可以使用索引那裏)。這是一個很瑣碎的查詢......

查詢計劃(與分析講解):

Bitmap Heap Scan on tab1 (cost=17.42..1760.21 rows=133 width=670) (actual time=0.603..0.603 rows=0 loops=1) 
    Recheck Cond: (((id)::text = 'A1000062'::text) AND (invoice IS NULL)) 
    Filter: ((charge IS NOT NULL) AND (client IS NULL) AND (releasetime < '2009-11-02'::date)) 
    -> Bitmap Index Scan on cdr_snapshot_2007_09_12_snbs_invoice (cost=0.00..17.39 rows=450 width=0) (actual time=0.089..0.089 rows=63 loops=1) 
    Index Cond: (((snbs)::text = 'A1000062'::text) AND (invoice IS NULL)) 
Total runtime: 0.674 ms 

自動清理的,我相信,啓用。沒有外鍵約束,但感謝提示,因爲我不知道這一點。

我真的很喜歡增加統計值的想法 - 我馬上就會玩一玩。

+1

查詢計劃是什麼樣子的,您是否啓用了autovacuum或是否定期執行真空(不運行autovacuum)。 – 2009-11-03 08:10:31

回答

0

您確實需要獲取一些查詢計劃,並編輯您的問題以包含它們。除了幫助找出更好的方法之外,還可以用它們來輕鬆衡量改進情況。


您可以通過更改SQL或通過調整用於確定查詢計劃的索引和統計信息來影響性能。


一種可能性是您有沒有支持索引的外鍵約束。當您創建外鍵約束時,PostgreSQL不會自動添加它們。如果被引用的表有一行被刪除(或被引用的字段被更新),則引用表將需要完全掃描,以級聯刪除或確保沒有引用已刪除行的行。


如果你的id字段的分佈是相當偏斜,該列增加統計數據可能幫助。

如果統計數據設置爲100,則會記錄100個最常見的ID(來自樣本)以及它們的頻率。假設覆蓋了大約50%的表格,剩下2到350萬行PostgreSQL會假設其他8900個ID, 或每個大約250到400次。

如果統計數據增加到1000,前1000個ID覆蓋你行的95%,PostgreSQL將假設不在你列表中的1000個最常見的ID將會出現大約30到40次。

估算值的變化會影響選定的查詢計劃。如果查詢模式更頻繁地選擇不太經常發現的id的id,PostgreSQL將過度估計id將被發現的次數。

存儲這麼多最常見的值會帶來性能成本,因此您確實需要支持查詢計劃分析以確定您是否獲得淨收益。