解決 RDS for PostgreSQL 中的清空效能問題 - Amazon Relational Database Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

解決 RDS for PostgreSQL 中的清空效能問題

本節討論通常有助於降低清空效能的因素,以及如何解決這些問題。

清空大型索引

VACUUM 此程序包含數個階段:初始化、掃描堆積、清空索引和堆積、清除索引、截斷堆積,以及執行最終清除。在掃描期間,頁面會遭到刪除、重組和凍結。完全掃描堆積後,索引會清除,空白頁面會傳回至作業系統,而最終清除任務會完成,例如清空可用空間貼圖和更新統計資料。

清空索引時,如果可用的 maintenance_work_mem(或 autovacuum_work_mem) 不足以處理索引,則可能需要多次通過。在 PostgreSQL 第 16 版及更早版本中,儲存無效元組 IDs 的記憶體配置限制為 1GB,通常需要多次傳遞,尤其是大型索引。PostgreSQL 第 17 版透過引入 來解決此限制TidStore,這是一種可取代單一配置陣列的動態記憶體配置系統。這可移除 1GB 限制條件、改善記憶體效率,並減少每個索引進行多次掃描的可能性。

不過,即使在 PostgreSQL 17 中,如果可用的記憶體不足以一次性處理整個索引,大型索引仍可能需要多次傳遞。一般而言,大型索引通常包含更多需要多次通過的無效元組。

偵測緩慢清空操作

postgres_get_av_diag() 函數可以偵測何時因為記憶體不足而緩慢執行清空操作。如需此函數的詳細資訊,請參閱 在 RDS for PostgreSQL 中安裝自動清空監控和診斷工具

當可用的記憶體不足以在單次傳遞中完成索引清空時,postgres_get_av_diag()函數會發出下列通知。

rds_tools 1.8

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
NOTICE: The current setting of autovacuum_work_mem is "XXX" and might not be sufficient. Consider increasing the setting, and if necessary, scaling up the Amazon RDS instance class for more memory. 
        Additionally, review the possibility of manual vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;).

rds_tools 1.9

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
NOTICE: The current setting of autovacuum_work_mem is XX might not be sufficient. Consider increasing the setting to XXX, and if necessary, scaling up the RDS instance class for more 
        memory. The suggested value is an estimate based on the current number of dead tuples for the table being vacuumed, which might not fully reflect the latest state. Additionally, review the possibility of manual 
        vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;). For more information, see Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide.
注意

postgres_get_av_diag() 函數依賴 pg_stat_all_tables.n_dead_tup來估算索引清空所需的記憶體量。

postgres_get_av_diag()函數識別由於 不足而需要多個索引掃描的慢速清空操作時autovacuum_work_mem,會產生下列訊息:

NOTICE: Your vacuum is performing multiple index scans due to insufficient autovacuum_work_mem:XXX for index vacuuming. 
        For more information, see Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide.

指引

您可以使用手動來套用下列解決方法VACUUM FREEZE,以加速凍結資料表。

增加用於清空的記憶體

postgres_get_av_diag()函數所建議,建議增加 autovacuum_work_mem 參數,以解決執行個體層級的潛在記憶體限制。雖然 autovacuum_work_mem 是動態參數,但請務必注意,若要讓新的記憶體設定生效,自動清空協助程式需要重新啟動其工作者。若要完成此操作:

  1. 確認新設定已就地。

  2. 終止目前執行自動清空的程序。

此方法可確保調整後的記憶體配置套用至新的自動清理操作。

如需更立即的結果,請考慮在工作階段中手動執行maintenance_work_mem設定增加VACUUM FREEZE的操作:

SET maintenance_work_mem TO '1GB'; VACUUM FREEZE VERBOSE table_name;

如果您使用 Amazon RDS,並發現需要額外的記憶體以支援 maintenance_work_mem或 的更高值autovacuum_work_mem,請考慮升級至具有更多記憶體的執行個體類別。這可提供必要的資源來增強手動和自動清空操作,進而改善整體清空和資料庫效能。

停用 INDEX_CLEANUP

PostgreSQL 第 12 版及更新版本VACUUM中的手動允許略過索引清除階段,而 PostgreSQL 第 14 版及更新版本中的緊急自動清空會根據 vacuum_failsafe_age 參數自動執行此操作。

警告

略過索引清除可能會導致索引膨脹,並對查詢效能產生負面影響。若要緩解這種情況,請考慮在維護時段重新編製索引或清空受影響的索引。

如需處理大型索引的其他指引,請參閱 上的文件使用大型索引管理自動清空

平行索引清空

從 PostgreSQL 13 開始,根據預設可以使用手動 平行清空和清理索引VACUUM,每個索引指派一個清空工作者程序。不過,對於 PostgreSQL 判斷清空操作是否符合平行執行的資格,必須符合特定條件:

  • 必須至少有兩個索引。

  • max_parallel_maintenance_workers 參數應設為至少 2。

  • 索引大小必須超過min_parallel_index_scan_size限制,預設為 512KB。

您可以根據 Amazon RDS 執行個體上可用的 vCPUs 數量和資料表上的索引數量來調整max_parallel_maintenance_workers設定,以最佳化清空周轉時間。

如需詳細資訊,請參閱 Amazon RDS for PostgreSQL 和 Amazon Aurora PostgreSQL 中的平行清空

要清空的資料表或資料庫過多

如 PostgreSQL 的 Autovacuum Daemon 文件所述,自動vacuum 協助程式會執行多個程序。這包括持久性自動清理啟動器,負責為系統內的每個資料庫啟動自動清理工作者程序。啟動器會排程這些工作者,每個資料庫大約每 autovacuum_naptime 秒啟動一次。

使用「N」資料庫時,大約每 【autovacuum_naptime/N 秒】 就會開始一個新工作者。不過,並行工作者的總數會受到 autovacuum_max_workers設定的限制。如果需要清空的資料庫或資料表數量超過此限制,工作者一到位就會立即處理下一個資料庫或資料表。

當許多大型資料表或資料庫需要同時清空時,所有可用的自動清空工作者都可以長時間佔用,進而延遲其他資料表和資料庫的維護。在交易率較高的環境中,此瓶頸可能會快速提升,並可能導致 Amazon RDS 執行個體中的包裝清空問題。

postgres_get_av_diag()偵測到大量資料表或資料庫時,會提供下列建議:

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
NOTICE: The current setting of autovacuum_max_workers:3 might not be sufficient. Consider increasing the setting and, if necessary, consider scaling up the Amazon RDS instance class for more workers.

指引

增加 autovacuum_max_workers

為了加速清空,建議您調整 autovacuum_max_workers 參數,以允許更多並行自動清空工作者。如果效能瓶頸持續存在,請考慮將 Amazon RDS 執行個體擴展到具有更多 vCPUs類別,這可以進一步改善平行處理功能。

正在執行積極式清空 (以防止包裝)

PostgreSQL 中資料庫 (MaximumUsedTransactionIDs 的存留期只會在積極清空 (防止包裝) 成功完成時縮短。在此清空完成之前,年齡會根據交易速率繼續增加。

postgres_get_av_diag() 函數偵測到積極的清空NOTICE時,會產生下列項目。不過,它只會在清空作用中至少兩分鐘後觸發此輸出。

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.

如需積極清空的詳細資訊,請參閱積極清空已執行時

您可以使用下列查詢來驗證積極清空是否正在進行中:

SELECT a.xact_start AS start_time, v.datname "database", a.query, a.wait_event, v.pid, v.phase, v.relid::regclass, pg_size_pretty(pg_relation_size(v.relid)) AS heap_size, ( SELECT string_agg(pg_size_pretty(pg_relation_size(i.indexrelid)) || ':' || i.indexrelid::regclass || chr(10), ', ') FROM pg_index i WHERE i.indrelid = v.relid ) AS index_sizes, trunc(v.heap_blks_scanned * 100 / NULLIF(v.heap_blks_total, 0)) AS step1_scan_pct, v.index_vacuum_count || '/' || ( SELECT count(*) FROM pg_index i WHERE i.indrelid = v.relid ) AS step2_vacuum_indexes, trunc(v.heap_blks_vacuumed * 100 / NULLIF(v.heap_blks_total, 0)) AS step3_vacuum_pct, age(CURRENT_TIMESTAMP, a.xact_start) AS total_time_spent_sofar FROM pg_stat_activity a INNER JOIN pg_stat_progress_vacuum v ON v.pid = a.pid;

您可以檢查輸出中的查詢資料欄,判斷是否為積極的清空 (以防止包裝)。片語「防止包裝」表示它是積極的清空。

query | autovacuum: VACUUM public.t3 (to prevent wraparound)

例如,假設您在交易年齡 10 億時有一個封鎖程式,以及需要積極清空的資料表,以防止在相同的交易年齡進行包裝。此外,交易年齡為 7.5 億的另一個封鎖程式。在交易 10 億齡時清除封鎖程式後,交易年齡不會立即下降到 7.5 億。在需要積極清空的資料表或任何超過 7.5 億的 交易完成之前,它將保持很高狀態。在此期間,PostgreSQL 叢集的交易期限會持續增加。清空程序完成後,交易使用期會降至 7.5 億,但會再次開始增加,直到進一步清空完成為止。只要這些條件持續存在,此週期就會繼續,直到交易期限最終降至 Amazon RDS 執行個體所設定的層級為止,由 指定autovacuum_freeze_max_age