當首次填充資料庫時,可能需要插入大量資料。本節包含一些關於如何使此過程盡可能高效的建議。
當使用多個 INSERT
時,關閉自動提交,並在最後只做一次提交。(在純 SQL 中,這表示在開始時發出 BEGIN
,在結束時發出 COMMIT
。某些客戶端函式庫可能會在背後執行此操作,在這種情況下,您需要確保函式庫在您想要完成時執行此操作。)如果您允許每次插入單獨提交,PostgreSQL 會為新增的每一列執行大量工作。在一個交易中完成所有插入的另一個好處是,如果某一列的插入失敗,那麼所有插入到該點的列都將回滾,因此您不會陷入部分載入的資料中。
COPY
#使用 COPY
在一個指令中載入所有列,而不是使用一系列 INSERT
指令。COPY
指令經過最佳化,可用於載入大量列;它不如 INSERT
靈活,但在載入大量資料時產生的額外負擔要少得多。由於 COPY
是一個單一指令,如果您使用此方法填充表格,則無需停用自動提交。
如果您無法使用 COPY
,則使用 PREPARE
建立準備好的 INSERT
陳述式,然後根據需要多次使用 EXECUTE
可能會有幫助。這樣可以避免重複解析和規劃 INSERT
的一些額外負擔。不同的介面以不同的方式提供此功能;在介面文件中尋找「預先準備好的陳述式」。
請注意,即使使用 PREPARE
並且多個插入分批到一個交易中,使用 COPY
載入大量列幾乎總是比使用 INSERT
快。
當 COPY
與先前的 CREATE TABLE
或 TRUNCATE
指令在同一個交易中使用時,速度最快。在這種情況下,不需要寫入 WAL,因為如果發生錯誤,包含新載入資料的檔案無論如何都會被移除。但是,只有當 wal_level 為 minimal
時,此考量才適用,因為所有指令都必須寫入 WAL,否則無法。
如果您要載入新建立的表格,最快的方法是建立表格,使用 COPY
大量載入表格的資料,然後建立表格所需的任何索引。在預先存在的資料上建立索引比在每次載入列時以累加方式更新它要快。
如果您要將大量資料新增到現有表格,則刪除索引、載入表格,然後重新建立索引可能是一種勝利。當然,在索引遺失期間,其他使用者的資料庫效能可能會受到影響。在刪除唯一索引之前也應該三思而後行,因為在索引遺失期間,唯一約束提供的錯誤檢查將會遺失。
如同索引一樣,外鍵約束可以更有效率地「批量」檢查,而非逐行檢查。因此,卸除外鍵約束、載入資料,然後重新建立約束可能很有用。同樣地,資料載入速度與約束遺失期間的錯誤檢查損失之間存在權衡。
更重要的是,當您將資料載入到具有現有外鍵約束的表格時,每個新資料列都需要在伺服器的待處理觸發事件清單中建立一個條目(因為檢查資料列的外鍵約束是透過觸發觸發器來完成的)。載入數百萬個資料列可能會導致觸發事件佇列溢出可用記憶體,進而導致無法忍受的交換或甚至直接導致命令失敗。因此,當載入大量資料時,卸除並重新套用外鍵可能不僅是理想的,而是必要的。如果暫時移除約束是不可接受的,則唯一的方法可能是將載入操作分成更小的交易。
maintenance_work_mem
#當載入大量資料時,暫時增加 maintenance_work_mem 設定變數可以改善效能。這將有助於加快 CREATE INDEX
命令和 ALTER TABLE ADD FOREIGN KEY
命令的速度。它對 COPY
本身沒有太大作用,因此只有在使用上述其中一種或兩種技術時,此建議才有用。
max_wal_size
#暫時增加 max_wal_size 設定變數也可以加快大型資料載入的速度。這是因為將大量資料載入到 PostgreSQL 中會導致檢查點發生的頻率高於正常檢查點頻率(由 checkpoint_timeout
設定變數指定)。每當發生檢查點時,所有髒頁都必須刷新到磁碟。透過在批量資料載入期間暫時增加 max_wal_size
,可以減少所需的檢查點數量。
當將大量資料載入到使用 WAL 歸檔或串流複製的安裝中時,在載入完成後取得新的基礎備份,可能比處理大量增量 WAL 資料更快。為了防止在載入時產生增量 WAL 日誌,請停用歸檔和串流複製,方法是將 wal_level 設定為 minimal
,將 archive_mode 設定為 off
,並將 max_wal_senders 設定為零。但請注意,變更這些設定需要重新啟動伺服器,並且使之前取得的任何基礎備份無法用於歸檔恢復和待命伺服器,這可能會導致資料遺失。
除了避免歸檔器或 WAL 發送器處理 WAL 資料的時間外,這樣做實際上會使某些命令更快,因為如果 wal_level
為 minimal
且目前的子交易(或最上層交易)建立或截斷了它們變更的表格或索引,則它們根本不需要寫入 WAL。(與寫入 WAL 相比,它們可以透過在最後執行 fsync
更便宜地保證當機安全性。)
ANALYZE
#無論何時您顯著改變了表格中資料的分配,強烈建議執行 ANALYZE
。這包括將大量資料批量載入到表格中。執行 ANALYZE
(或 VACUUM ANALYZE
)可確保規劃器具有關於表格的最新統計資訊。如果沒有統計資訊或統計資訊已過時,規劃器可能會在查詢規劃期間做出錯誤的決定,從而導致任何具有不準確或不存在的統計資訊的表格效能不佳。請注意,如果啟用了 autovacuum 守護程序,它可能會自動執行 ANALYZE
;有關更多資訊,請參閱 Section 24.1.3 和 Section 24.1.6。
由 pg_dump 產生的傾印腳本會自動套用一些(但不是全部)上述準則。為了盡可能快速地恢復 pg_dump 傾印,您需要手動執行一些額外的操作。(請注意,這些點適用於恢復傾印,而不是建立傾印時。無論是使用 psql 載入文字傾印,還是使用 pg_restore 從 pg_dump 封存檔案載入,這些點都適用。)
預設情況下,pg_dump 使用 COPY
,並且在產生完整的綱要和資料傾印時,它會小心地在建立索引和外鍵之前載入資料。因此,在這種情況下,會自動處理幾個準則。您需要做的是:
為 maintenance_work_mem
和 max_wal_size
設定適當的(即大於正常的)值。
如果使用 WAL 歸檔或串流複製,請考慮在還原期間停用它們。為此,請在載入傾印之前將 archive_mode
設定為 off
,將 wal_level
設定為 minimal
,並將 max_wal_senders
設定為零。之後,將它們設定回正確的值,並取得新的基礎備份。
實驗 pg_dump 和 pg_restore 的平行傾印和還原模式,並找到要使用的最佳並行作業數。透過 -j
選項以平行方式傾印和還原應該比序列模式提供更高的效能。
考慮是否應將整個傾印還原為單一交易。為此,請將 -1
或 --single-transaction
命令列選項傳遞給 psql 或 pg_restore。當使用此模式時,即使是最小的錯誤也會回滾整個還原,可能會丟棄數小時的處理時間。根據資料的相互關聯程度,這可能比手動清理更可取,也可能不是。COPY
命令在您使用單一交易並關閉 WAL 歸檔時,執行速度最快。
如果資料庫伺服器中有多個 CPU 可用,請考慮使用 pg_restore 的 --jobs
選項。這允許並行資料載入和索引建立。
之後執行 ANALYZE
。
僅匯入資料的傾印檔仍會使用 COPY
,但不會捨棄或重建索引,通常也不會更動外部鍵。[14] 因此,在載入僅匯入資料的傾印檔時,如果您希望使用這些技巧,則需要自行捨棄並重建索引和外部鍵。 在載入資料時增加 max_wal_size
仍然很有用,但不用費心增加 maintenance_work_mem
;相反地,您應該在之後手動重建索引和外部鍵時才這麼做。 並且別忘了在完成後執行 ANALYZE
;請參閱第 24.1.3 節和第 24.1.6 節以獲取更多資訊。
如果您在文件中看到任何不正確、與您特定功能的使用經驗不符或需要進一步澄清的地方,請使用此表單回報文件問題。