2012-10-17 36 views
8

我有一個10米行的大桌子。我需要爲每一行獲得一些統計值。我有生成此值的函數,例如GetStatistic(uuid)。該功能的工作原理很慢,結果值變化不常有,所以我在我的表中創建列Statistic,並且一天一次執行這樣的查詢:Postgresql。可以在paralell中運行更新查詢嗎?

UPDATE MyTable SET Statistic = GetStatistic(ID); 

而且在選擇查詢我使用列Statistic不調用GetStatistic功能。

的問題是,我的生產服務器有64個CPU和大量的內存,所以幾乎所有的數據庫可以被緩存到內存,但此查詢只使用一個CPU,需要2到3個小時來執行。

GetStatistic函數使用表,它在UPDATE查詢的所有執行期間都是不變的。我是否可以修改查詢來讓postgre同時使用所有可用的CPU來爲不同的行計算並列中的GetStatistic?

+0

爲什麼使用函數,有沒有什麼不能用普通的SQL來完成的?該函數只需要當前行的值還是還包含其他數據源(:=表)?順便說一句:向我們展示功能。 – wildplasser

+0

查看這個查詢的計劃,你會看到這個函數被稱爲10M次。也許用純SQL編寫它會更好,並且速度可能會更快。 –

回答

9

PostgreSQL在單個後臺執行每個查詢,這是一個單線程進程。它不能使用多個CPU進行查詢。它在一次查詢中可以實現的I/O併發性也有所限制,實際上只爲位圖索引掃描執行併發I/O,並且依賴操作系統和磁盤系統進行併發I/O。

Pg擅長處理許多較小查詢的併發負載,並且很容易讓系統飽和,這樣做並不能爲一兩個真正的大問題提供最好的系統資源。

你可以做的是將工作分成塊並交給工人。你提到這種搭配:

我可以修改查詢以獲得postgre計算GetStatistic在相同常 同時爲不同的行,使用所有avaliable的CPU?

有各種各樣的工具,如DBlinkPL/ProxypgbouncerPgPool-II,旨在幫助這種工作。或者,您可以自己動手,開始(例如)8個工作人員,每個工作人員連接到數據庫並執行具有非重疊ID範圍的UPDATE ... WHERE id BETWEEN ? AND ?語句。更復雜的選擇是讓隊列控制器向UPDATE範圍內的工作人員提供約1000個ID的範圍,然後再請求一個新的範圍。

請注意,64個CPU並不意味着64個併發工作者是理想的。在寫入時,磁盤I/O也是一個因素。如果您將UPDATE事務設置爲使用commit_delay和(如果您對此數據的業務需求安全)synchronous_commit = 'off',那麼您可以幫助您減少I/O成本,那麼同步的負載應顯着降低。儘管如此,最好的吞吐量可能會遠低於64位併發工作者。

很可能您的GetStatistic函數可以通過將其轉換爲可嵌入的SQL函數或視圖而使其速度大大提高,而不是假設它現在是一個循環繁重的過程式PL/pgSQL函數。如果你顯示這個功能可能會有所幫助。

相關問題