PostgreSQL 批量數(shù)據(jù)加載導入,加速性能的七大江湖絕技
當前位置:點晴教程→知識管理交流
→『 技術(shù)文檔交流 』
背景有時,PostgreSQL 數(shù)據(jù)庫需要通過單個或最少的步驟,來導入大量數(shù)據(jù)。這通常稱為批量數(shù)據(jù)導入,其中數(shù)據(jù)源通常是一個或多個大文件。這個過程有時可能會慢得令人無法接受。 導致性能如此糟糕的原因有很多,例如:索引、觸發(fā)器、外鍵、GUID 主鍵,甚至預寫式日志(WAL)也可能導致延遲。 在本文中,我們將介紹將數(shù)據(jù)批量導入 PostgreSQL 數(shù)據(jù)庫的一些最佳實踐技巧。但是,在某些情況下,這些方法也可能都不是那么有效。我們建議您在應用任何方法之前,先考慮好它的優(yōu)缺點。 方法 1: 將目標表更改為 UNLOGGED 模式對于 PostgreSQL 9.5 及更高版本,可以先將目標表更改為 UNLOGGED,然后在加載完數(shù)據(jù)后將其更改回 LOGGED:
UNLOGGED 模式可確保 PostgreSQL 不會將表的寫入操作記錄到預寫式日志(WAL)。這可以使加載過程非常快。但是,由于未記錄操作日志,因此,如果在加載期間服務器發(fā)生崩潰或不正常的停機,則無法恢復數(shù)據(jù)。PostgreSQL 將在重新啟動后自動截斷任何 UNLOGGED 模式的表。 此外,UNLOGGED 模式的表不會同步到備用服務器。在這種情況下,必須在加載之前刪除現(xiàn)有的復制,并在加載后重新創(chuàng)建現(xiàn)有復制。根據(jù)主節(jié)點中的數(shù)據(jù)量和備用節(jié)點的數(shù)量,重新創(chuàng)建復制的時間可能相當長,并且無法滿足高可用的要求。 我們建議采用以下最佳實踐,將數(shù)據(jù)批量插入到 UNLOGGED 模式的表中:
方法 2: 刪除并重新創(chuàng)建索引現(xiàn)有索引可能會導致批量數(shù)據(jù)插入期間出現(xiàn)嚴重延遲。這是因為在添加每一行時,相應的索引記錄也必須更新。 我們建議在開始批量插入之前,盡可能刪除目標表中的索引,并在加載完成后重新創(chuàng)建索引。同樣,在大型表上創(chuàng)建索引可能很耗時,但通常比在加載期間更新索引更快。
在創(chuàng)建索引之前,臨時調(diào)大 maintenance_work_mem 配置參數(shù)可能是值得的。增加的工作內(nèi)存有助于更快地創(chuàng)建索引。 另一個安全的措施是,在同一數(shù)據(jù)庫中創(chuàng)建目標表的副本,其中包含現(xiàn)有數(shù)據(jù)和索引。然后,可以使用這個新復制的表,對批量插入測試兩種情況:刪除并重新創(chuàng)建索引,或動態(tài)更新索引。然后,就可以將性能驗證更好的方法應用到生產(chǎn)表上面。 方法 3: 刪除并重新創(chuàng)建外鍵與索引一樣,外鍵約束也會影響批量加載性能。這是因為必須檢查每個插入行中的每個外鍵是否存在相應的主鍵。在后臺,PostgreSQL 使用觸發(fā)器來執(zhí)行檢查。加載大量行時,必須為每行觸發(fā)此觸發(fā)器,這會增加開銷。 除非受業(yè)務規(guī)則限制,否則我們建議從目標表中刪除所有外鍵,在單個事務中加載數(shù)據(jù),然后在提交事務后重新創(chuàng)建外鍵。
同樣,調(diào)大 maintenance_work_mem 配置參數(shù),可以提高重新創(chuàng)建外鍵約束的性能。 方法 4: 禁用觸發(fā)器INSERT 或 DELETE 觸發(fā)器(如果加載過程還涉及從目標表中刪除記錄)可能會導致批量數(shù)據(jù)加載延遲。這是因為,每個觸發(fā)器在每行被 INSERT 或 DELETE 后,都有需要檢查的邏輯和需要立即完成的操作。 我們建議,在批量加載數(shù)據(jù)之前禁用目標表中的所有觸發(fā)器,并在加載完成后啟用它們。禁用的所有觸發(fā)器也包括強制執(zhí)行外鍵約束檢查的內(nèi)部觸發(fā)器。
方法 5: 使用 COPY 命令我們建議使用 PostgreSQL 的 COPY 命令,從一個或多個文件加載數(shù)據(jù)。COPY 針對批量數(shù)據(jù)加載進行了優(yōu)化。它比運行大量 INSERT 語句或者多行 INSERT 都要更加高效。
使用 COPY 的其他好處包括:
方法 6: 使用多行 INSERT對于批量數(shù)據(jù)加載來說,運行幾千或幾十萬個 INSERT 語句,可能是一個糟糕的選擇。這是因為,每個單獨的 INSERT 命令都必須由查詢優(yōu)化器解析和準備,完成所有約束檢查,作為單獨的事務運行,并記錄在 WAL 中。使用多行的單個 INSERT 語句可以節(jié)省此開銷。
多行 INSERT 的性能受現(xiàn)有索引的影響。我們建議在運行命令之前刪除索引,然后在運行之后重新創(chuàng)建索引。 另一個需要注意的方面是,PostgreSQL 可用于運行多行 INSERT 的內(nèi)存大小。當運行多行 INSERT 時,內(nèi)存中必須要容納大量的輸入值,除非有足夠的可用內(nèi)存,否則該過程可能會失敗。 我們建議將 effective_cache_size 參數(shù)設(shè)置為機器總內(nèi)存的 50%,shared_buffer 參數(shù)設(shè)置為總內(nèi)存的 25%。此外,為了安全起見,最好運行一系列的多行 INSERT,每條語句都有 1000 行的值。 方法 7: 運行 ANALYZE這與提高批量數(shù)據(jù)導入性能無關(guān),但我們強烈建議,在批量導入后立即對目標表運行 ANALYZE 命令。大量新行會顯著改變列中的數(shù)據(jù)分布,并導致表上的任何現(xiàn)有統(tǒng)計信息過時。當查詢優(yōu)化器使用過時的統(tǒng)計信息時,查詢性能可能會差得令人無法接受。運行 ANALYZE 命令,可以確保任何現(xiàn)有的統(tǒng)計信息得到更新。 最后的思考數(shù)據(jù)庫應用程序可能并非每天都要進行批量數(shù)據(jù)導入,但運行時會對查詢的性能產(chǎn)生影響。這就是為什么有必要盡可能減少加載時間的原因。為了最大限度地減少任何意外,DBA 可以做的一件事是,在具有類似服務器規(guī)格和 PostgreSQL 配置的開發(fā)環(huán)境或灰度環(huán)境中,測試負載的優(yōu)化效果。每個數(shù)據(jù)加載方案都是不同的,最好嘗試下每種方法,并找出最有效的方法。 該文章在 2024/9/13 8:50:23 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |