PostgreSQL ANALYZE 執行時間超過 24 小時(仍在執行)
我使用 pg_upgrade(就地)升級了 Postgres DB 9.3.2–>10.5。我根據文件和 pg_upgrade 給出的說明做了所有事情。一切都很順利,但後來我意識到其中一張表中沒有使用索引(也許其他表也受到了影響)。
所以我
ANALYZE
昨天在那個桌子上開始了一個仍在執行(超過 22 小時)……!問題:
ANALYZE
執行時間這麼長正常嗎?該表包含大約 30M 條記錄。結構是:
CREATE TABLE public.chs_contact_history_events ( event_id bigint NOT NULL DEFAULT nextval('chs_contact_history_events_event_id_seq'::regclass), chs_id integer NOT NULL, event_timestamp bigint NOT NULL, party_id integer NOT NULL, event integer NOT NULL, cause integer NOT NULL, text text COLLATE pg_catalog."default", timestamp_offset integer, CONSTRAINT pk_contact_history_events PRIMARY KEY (event_id) ); ALTER TABLE public.chs_contact_history_events OWNER to c_chs; CREATE INDEX ix_chs_contact_history_events_chsid ON public.chs_contact_history_events USING hash (chs_id) TABLESPACE pg_default; CREATE INDEX ix_chs_contact_history_events_id ON public.chs_contact_history_events USING btree (event_id) TABLESPACE pg_default; CREATE INDEX ix_history_events_partyid ON public.chs_contact_history_events USING hash (party_id) TABLESPACE pg_default;
更新:
我執行下面的查詢以獲取目前正在執行的程序並得到了一個非常有趣的結果:
SELECT pid, now() - pg_stat_activity.query_start AS duration, query, state FROM pg_stat_activity WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes' AND state = 'active';
似乎維護任務和索引表的並發重建都被凍結了!
那麼下一個問題:取消這些程序是否安全?下一步該怎麼做?IMO 停止它們並重新創建索引是必要的,但我不確定。
附件 1
在 v9 中更正的可能相關錯誤:
9.3.7 和 9.4.2 修復雜湊索引桶拆分期間可能出現的故障,如果其他程序正在同時修改索引
9.3.18 和 9.4.13 和 9.5.8 和 9.6.4 修復 Windows 版本中共享謂詞鎖雜湊表的低機率損壞
9.5.4 修復大(大於shared_buffers)雜湊索引的建構 用於大索引的程式碼路徑包含一個錯誤,導致錯誤的雜湊值插入索引,因此後續索引搜尋總是失敗,除了插入索引的元組在初始建構之後。
在 v10 中更正的可能相關錯誤:
10.2 修復在添加新的溢出頁面後無法將雜湊索引的元頁面標記為臟,可能導致索引損壞
防止由於簡單雜湊表的過度增長而導致的記憶體不足故障
最後但並非最不重要的一點是,這讓我感到擔憂(因為升級在生產環境中似乎不現實):
10.6 當 BLCKSZ 小於預設值時,避免雜湊索引的元頁溢出
修復散列索引中錯過的頁面校驗和更新
附件 2
v10升級說明:
在從任何以前的主要 PostgreSQL 版本進行 pg_upgrade-ing 之後必須重建雜湊索引
主要的雜湊索引改進需要此要求。pg_upgrade 將創建一個腳本來幫助解決這個問題。
請注意,我當然在升級時執行了該腳本。
經過幾個小時的研究和檢查目前情況,我想我設法解決了這個問題。(非常感謝其他使用者 ypercube 的靈感和同時提出相同解決方案的 Erwin Brandstetter。)
所以有幾個層面的問題。
1.) 升級
使用 pg_upgrade 9.3.2 升級 –> 10.5 應該分兩步進行。首先在同一行(9.3.2 –> 9.3.25),然後到 10.x(在我的情況下為 10.5)
我進行了直接升級,似乎這是問題的根本原因。
2.) 雜湊索引
似乎雜湊索引在 postgres 中遇到了一些奇怪的錯誤,這些錯誤已經被糾正,但是使用預糾正版本的索引會導致錯誤
3.) 凍結任務
尋找長時間執行的 postgres 程序確實有意義。(請參閱問題中的查詢。)在我的情況下,結果發現索引的重新創建以某種方式卡住了,並且其他幾個任務也被阻止了。
使用pid是在上述查詢的結果集中找到的程序 ID可以安全地取消其中的大多數
SELECT pg_cancel_backend(__pid__);
。所以我做到了。我什至停止了 autovacuum 程序。4.) 記憶體處理
在這一切之後,我終於認為我能夠刪除並創建新索引,我面臨下一個問題。大約一分鐘後,所有維護查詢都退出並顯示錯誤消息:
ERROR: out of memory DETAIL: Failed on request of size 22355968. SQL state: 53200
似乎記憶體處理在 9.3 和 10 之間發生了變化。我不得不減少配置中的 maintenance_mem 數量:
maintenance_work_mem = 64MB # min 1MB
之前是 512MB,儘管伺服器有 32GB 的 RAM,但它仍然無法使用。
5.) 重新創建索引
畢竟可以重新創建索引(刪除舊索引並創建新索引)。使用適當的腳本會更容易,但我必須手動完成。不要忘記創建和刪除索引會鎖定表,因此在生產環境(如我的環境)中您應該同時執行此操作。
編輯:
我還意識到在我的特定情況下使用雜湊索引並沒有真正的意義,所以我決定在遊戲中將它們更改為 btree。
6.) 分析
重新創建索引後,有必要對受影響的表(或整個數據庫)執行分析。經過上述所有操作,即使在像我這樣的巨大數據庫中,它也會以驚人的速度執行。
索引再次被使用,性能再次完美。所以這是我在 StackExchange 的第一篇文章中的一個快樂結局。:-)