Postgresql
更新數千個表行哪個更快?
使用PostgreSQL v10.1.2 中的儲存過程,這是最快的還是更好的方法:檢查行是否存在然後更新或嘗試直接更新,可能找不到符合條件的行?我需要檢查很多具有相同條件的表格,表格是
不是“非規範化”,我做了幾個測試,有時選項 1在其他情況下更快,選項 2 …選項1:
IF EXISTS ( SELECT 1 FROM public.table1 WHERE column1 = 'oldvalue' ) THEN UPDATE public.table1 SET column1 = 'newvalue' , date_update= .... WHERE column1 = 'oldvalue'; END IF ;
選項 2:
UPDATE public.table1 SET column1 = 'newvalue' , date_update= ... WHERE column1 = 'oldvalue';
選項 3:
perform FROM public.table1 WHERE column1 = 'oldvalue' ; if found then UPDATE public.table1 SET column1='newvalue', date_update = ... WHERE column1 = 'oldvalue'; end if ;
我做了:
BEGIN; EXPLAIN ANALYZE VERBOSE select a_test_w_perform(); ROLLBACK;
對於每個選項,時間平均值各不相同,時間結果類似於:
- 選項1
Query returned successfully in 311 msec. / 423 msec./ 242 msec./ 367
- 選項 2
Query returned successfully in 308 msec. / 307 msec./311 msec./ 200
*選項 3
Query returned successfully in 204 msec./ 279 msec./451 msec. / 230
通常只嘗試
UPDATE
.發布
SELECT
第一個,只會增加讀取成本。另外,更重要的是,無論如何,在對數據庫的並發寫入負載下它是不可靠的。您必須添加FOR UPDATE
或類似內容才能鎖定行。但是不要。只需發出UPDATE
.但是,在許多情況下提高性能的一種方法是:避免空更新:
UPDATE public.table1 SET column1 = 'newvalue' , date_update = ... WHERE column1 = 'oldvalue' AND (column1 , date_update) IS DISTINCT FROM ('newvalue', ... ); -- to skip empty updates
有關的:
SELECT
如果您想參與(或類似),則首先發布是有意義的LIMIT
,這是不允許UPDATE
直接參與的。但考慮並發:產生的性能可能因許多參數而異。暖記憶體、並發事務、伺服器負載等。您的情況可能特別棘手:
檢查許多具有相同條件的表
涉及大量表使得很難找到最佳查詢計劃。如果你知道某個謂詞特別有選擇性——而 Postgres 沒有——那麼首先執行一個廉價的、簡化的可能是值得的
SELECT
。但是您需要正確處理並發。通常,這表明您的查詢或伺服器配置存在與成本設置或統計資訊有關的問題,最好解決該問題而不是解決該問題。但是 Postgres 確實有一些盲點,比如沒有針對多個條件的組合統計資訊,或者沒有針對文件類型中的嵌套值的統計資訊
jsonb
,xml
等等。更新: Postges 10 添加了“多列優化器統計資訊來計算相關比率和不同值的數量”。(對於嵌套在文件類型中的值仍然沒有幫助。)手冊中的詳細資訊。
更新整個表的大部分內容時,可能會採用不同的策略: