PostgreSQL 數據庫服務器內存不足?可以這么做
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
內存使用是數據庫系統最重要的方面之一。內存不足會直接影響每個性能指標,并對性能產生負面影響。這反過來又會影響我們的用戶和業務。在本文中,我們將了解 PostgreSQL 數據庫如何管理內存,以及如何排查可用內存不足的問題。 數據庫如何讀取數據要了解如何處理內存,我們需要了解事情是如何運作的。讓我們來看一些基本的數據庫和操作系統機制。 內存頁數據庫組織數據的方式,需要能提高性能,并使讀取和寫入更易于處理。為了實現最佳性能,業務負載必須是可預測的,并劃分為可管理的塊。數據庫通過頁面來實現這一點。 數據庫上下文中的頁是一個固定長度的數據塊,它表示數據庫系統處理的最小存儲單位。頁面允許數據庫有效地組織磁盤上的數據,這反過來又可以提高性能,并使業務負載可預測。 頁面大小參數決定頁面的大小。通常,它設置為 8192 字節(8kB),某些數據庫允許用戶對其進行配置,例如,PostgreSQL 中的 block_size。頁面可以分組到所謂的區中,這使得頁面管理更容易。 數據庫有效地存儲在頁面中。每次磁盤讀取或寫入,最終都會讀取或寫入整個頁面,這意味著會寫入 8 KB 的數據。即使我們想讀取一個字節的數據(比如表中一行的單個比特位的列),我們也需要將整個頁面加載到內存中。 碎片化通常,數據庫將一個表行僅存儲在一個頁面上。它們不允許將行存儲在多個頁面上。這會導致一種稱為碎片化的現象。每行可能具有不同的長度,特別是如果我們使用可變長度類型,例如 預讀和性能當訪問的頁面構成一個連續的內存塊時,讀取和寫入的速度要快得多。這利用了內存預取機制,其中內存管理單元(MMU)會進行預測,在不久的將來可能訪問哪些內存頁,并更早地加載它們。如果預測正確,則整體性能會隨著 MMU 更早地讀取數據而提高。為了更好地進行預測,內存頁必須構成一個連續的塊(因此頁面必須一個接一個地出現在物理內存中)。 典型的頁面大小為 8 KB。這在大多數情況下都很有效,但是,有時我們希望擁有更大的頁面,以減少讀寫操作的次數。頁面大小主要由操作系統和 CPU 架構決定。由于操作系統通常使用 8kB 頁面,因此數據庫系統希望使用相同的設置。為了減少 I/O 操作的次數,我們需要使頁面更大。為此,我們可以使用長度為 2MB、1GB 甚至 16GB 的所謂大頁面。我們需要在操作系統中啟用它們,然后在數據庫中啟用它們。例如,PostgreSQL 為此提供了 huge_page_size 參數。通過啟用大頁面,數據庫可以獲得更大的頁面,從而減少數據庫必須執行的 I/O 讀取和寫入次數。這也使頁面能構成更大的連續塊,從而提高預取和整體性能。 但是,操作系統可能會動態調整頁面大小。例如,Linux 支持透明大頁面(THP),它會自動提升和降低頁面大小。這會對應用程序隱藏大頁面,理論上可以在應用程序沒有使用大頁面時提高性能,因為操作系統可能會將多個應用程序的頁面合并為一個大頁面。遺憾的是,當應用程序顯式使用大頁面,而操作系統在后臺將大頁面表示為常規頁面時,性能會很快下降。如果您在數據庫中啟用了大頁面,請在操作系統中禁用 THP。 內存過量使用在為應用程序分配的內存量方面,操作系統也可能會作弊。當應用程序嘗試分配內存時,即使沒有可用的內存,操作系統也始終會確認內存已分配。這稱為內存過量使用。 此方法可在許多應用程序運行時提高系統的可用性。在準備處理輸入的數據時,應用程序分配的緩沖區通常比所需的緩沖區更大。即使應用程序不使用這些內存,操作系統也需要分配大塊內存,這會很快耗盡資源,并且能夠運行的應用程序更少。 為避免此問題,操作系統假裝所有內存分配都已完成,并且內存是可用的。只有當應用程序嘗試訪問數據時,操作系統才會引發內存不足的異常。在這種情況下,可能會啟動 Out-of-Memory-Killer,并殺死其中一個進程。當應用程序不想使用比機器物理內存更多的內存時,這一切都很好。如果他們想使用它,那么問題就開始了。 數據庫通常就是這種情況。他們希望在開始時分配大塊內存,以便為任何業務負載做好準備。不幸的是,即使內存不可用,操作系統也會簡單地假裝內存已分配。因此,請在您的操作系統中禁用內存過量使用。在 Linux 中,您可以使用 vm.overcommit_memory 參數。 PostgreSQL 如何分配內存當 PostgreSQL 服務器啟動時,它會分配許多不同的內存塊。讓我們一一看看。 共享緩沖區最重要的內存塊稱為共享緩沖區。它是用于緩存最常用的頁面的內存塊(涵蓋了數據庫中的行、索引和其他內容)。數據庫會使用幾個指標,來識別最受歡迎的頁面,但它們主要歸結為對讀取和寫入進行計數。有趣的是,您甚至可以讀取頁面,并將其重定向到 共享緩沖區在開始時分配,在運行期間無法更改它們的大小。因此,要更改大小,您需要重新啟動數據庫。 共享緩沖區是數據庫內存中最重要的部分。默認大小設置為 128MB,一般建議將其設置為機器內存的 25%。但是,這是一個非常古老且不準確的建議,因此請繼續閱讀以了解如何調整它,也可參閱我們另一篇文章,關于如何處理緩存命中率低的問題,以了解更多信息。 工作內存另一個內存塊是,為每個查詢中的每個執行節點分配的工作內存。此內存用于處理節點的輸出,并生成結果。因此,我們擁有的查詢和節點越多,我們使用的內存就會越多。 要了解其工作原理,我們需要了解查詢是如何執行的。每當我們運行查詢時,數據庫必須分階段執行它。首先,它從表中提取數據并進行連接。接下來,數據庫執行過濾和其他處理。最后,對結果進行排序。在每個階段,數據庫可能需要生成一大塊數據(比如一個表的內容),這會消耗大量內存。 無需過多的論述,每一個此類型的操作都可能是執行計劃中的一個節點。因此,要從多個表進行讀取的一個查詢,可能具有多個執行計劃節點。對于每個這樣的節點,數據庫都會分配工作內存。如果節點的結果集大于工作內存,則會溢出到磁盤(這比將數據保存在內存中要慢得多)。 PostgreSQL 中的 work_mem 設置,控制為每個查詢中的每個執行節點分配的內存量。默認情況下,它設置為 4MB。通常建議將此參數設置為總內存量除以連接數,然后再除以 4 或 16。這取決于您正在運行的業務負載,因此請繼續閱讀以了解如何對其進行優化。 維護工作內存我們要考慮的下一個內存塊是維護工作內存。該內存塊用于執行后臺操作,如清理(碎片整理)、索引創建或 DDL 操作(比如添加外鍵)。 每個后臺任務都有自己的內存塊,因此,如果有許多 autovacuum 進程正在運行,則每個進程都會有自己的內存塊。默認情況下,該內存塊的大小設置為 64MB。如果您的服務器有足夠的內存,通常建議將其設置為更高的值,例如 1GB。 臨時緩沖區每個會話還會獲得另一個用于會話本地緩沖區的內存塊。該內存塊用于創建臨時數據,如臨時表。會話會根據需要分配臨時緩沖區。 默認情況下,允許每個會話分配 8MB 的臨時緩沖區。此內存不與其他會話共享,并且是會話專用的。如果您處理的會話需要分配許多臨時表,則可以考慮調整此參數。 內存調優現在讓我們看看,如何對 PostgreSQL 服務器中的內存進行調優。 靜態配置首先,您需要做配置的調優。 shared_buffers對 內存利用率在很大程度上取決于您與數據的交互方式。如果您運行的是一個 OLTP 系統,那么我們可以假設,許多事務將在短時間內觸及相同的行。在這種情況下,緩存這些行而不是一遍又一遍地從磁盤中檢索它們會是有益的。在這種情況下,增加緩存大小是一個好主意。 但是,如果您運行的是數倉或報表分析數據庫,則不太可能在短時間內讀取任何行兩次。這意味著緩存數據沒有意義。相反,我們應該讓緩存更小! 如果運行的是 OLTP 業務,則優化 shared_buffers 參數的實際過程應如下所示:
如果您運行 OLAP 或數倉,則可以使用相同的策略,來減小緩存的內存大小,而不會降低系統的性能。請參閱我們關于如何處理緩存命中率低的問題的文章,以了解更多信息。 work_mem應根據您在數據庫中配置的連接數,來設置 work_mem 參數。在獲得連接數后,可這樣計算
如果您觀察到仍然有許多查詢會溢出到磁盤,請將 work_mem 參數值繼續加倍,直到您的查詢不再經常溢出。 maintenance_work_mem將 temp_buffers將 連接每個連接都會消耗一些內存。連接過多會降低系統性能,并消耗大量內存。因此,您應該限制連接數,并盡可能使用連接池。 請參閱我們的配置連接池指南,了解如何配置它們。 查詢優化很明顯,慢查詢可能會影響到可用的內存量。低效的查詢可能會讀取過多數據(通過掃描表而不是使用索引)、溢出到磁盤(通過使用低效的連接策略)或降低緩存命中率(通過更新未使用的索引)。 因此,請始終優化好查詢。分析他們的連接策略、查詢參數、過濾器、溢出到磁盤,以及會降低性能的其他方面。 索引未使用的索引可能會降低您的可用內存。每次更新表中的數據時,可能還需要更新索引。即使未使用的索引,它們也需要與表保持同步。這意味著更新表中的行,可能會導致執行更多的更新。 此處的一般建議是,刪除所有未使用的索引。在查找未使用的索引時,請考慮以下事項:
如果您確定該索引未被使用,則只需將其刪除即可。如果您觀察到某些查詢的性能下降,請分析其歷史性能(如果它們在刪除索引時,速度會變慢)。如果是這樣的話,那么也許他們還是使用了索引。 操作系統配置如前所述,您的操作系統配置可能會影響數據庫的性能。一般建議禁用內存過量使用和透明大頁面。請查閱您的操作系統的文檔,以了解如何執行此操作。 緩存命中率通常,提高緩存命中率的所有步驟,也都可能改善可用內存不足的情況。請參閱我們關于如何處理緩存命中率低的問題的指南。 表分區請對表進行分析,是否可以對表進行分區。有很多方法可以進行分區,您可以按照我們的表分區指南,了解更多信息。 擴展如果都沒有什么幫助,您可以考慮擴展服務器。您可以使機器更大(垂直擴展)或將負載分布到多臺機器(水平擴展)。可以從垂直擴展開始,因為它要容易得多。如果這沒有幫助,請考慮水平擴展,但請記住,這可能需要更改數據庫客戶端。 總結可用內存低的問題可能會很難處理。我們需要明白,許多活動的部分是相互關聯的。我們需要分析我們的操作系統配置、數據庫配置和我們應對的業務負載。OLTP 和 OLAP 系統的情況不同,沒有通用的解藥。 該文章在 2024/11/18 9:00:16 編輯過 |
關鍵字查詢
相關文章
正在查詢... |