PostgreSQL 硬件性能調優

PostgreSQL 硬件性能調優

翻譯自文章《PostgreSQL Hardware Performance Tuning》html

PostgreSQL是一個由世界範圍內開發人員在互聯網上開發的對象-關係型數據庫。她是商業數據庫如Oracle和Informix一個開源替代。sql

PostgreSQL最初由加大伯克利分校開發。在1996年,一個團隊開始在互聯網上開發這個數據庫。他們經過郵件來交流思想而且經過文件服務器來共享代碼。PostgresSQL如今在專業特性、性能、可靠性上比得上商業數據庫。她具備事務、視圖、存儲過程、引用一致性約束。她支持許多編程接口,包括ODBC、Java(JDBC)、TCL/TK、PHP、Perl和Python。得益於一大批有才幹的網絡開發者,PostgreSQL 繼續以驚人的速度提高 。數據庫

性能概念

有兩個方面的數據庫性能調優。一個是提升數據庫服務器使用的CPU、內存、磁盤驅動。第二個是優化發送到數據庫的查詢。這篇文章討論硬件方面的性能調優。查詢優化能夠經過SQL命令如 CREATE INDEX、VACUUM 、VACUUM FULL、ANALYZE、CLUSTER 和 EXPLAIN 來完成。這些在《PostgreSQL:Introduction and Concepts》中討論在 http://momjian.us/main/writings/pgsql/aw_pgsql_book/編程

爲了理解硬件調優問題,理解計算機里正在發生什麼是很是重要的。簡單來講,計算機能夠想象成一個被存儲包圍着的CPU。在和CPU同一芯片上是幾個用來存儲中間結果和不一樣指針和計數的CPU寄存器。在這些周圍是用來保存最近訪問信息的CPU緩存。在CPU緩存外面是大量的用來保存正在執行程序和數據的隨機訪問主存(RAM)。在主存的外面是存儲更多信息的磁盤驅動。磁盤驅動是惟一的持久存儲區,因此任何要在關機後保持的信息都必須放在那裏。總之,在CPU的周圍有這些存儲:
這裏寫圖片描述緩存

存儲區域 度量單位
CPU 寄存器 bytes
CPU 緩存 kilobytes
RAM megabytes
磁盤驅動 gigabytes

你能夠看到距離CPU越遠存儲越大。理論上,大量的持久存儲能夠放在CPU旁邊,可是會特別慢且比較昂貴。在實踐中,常常被使用的信息存儲在CPU旁邊,不常常訪問的信息存儲遠離CPU,當使用時被帶到CPU。安全

保持信息靠近CPU

在不一樣存儲區之間移動信息是自動發生的。編譯器決定哪些信息保存在寄存器中。CPU芯片邏輯保證最近使用的信息保存在CPU緩存中。操做系統控制哪些信息存儲在RAM並在磁盤驅動器間來回穿梭。服務器

CPU寄存器和CPU緩存不能被數據庫管理員有效的調優。有效的數據庫調優涉及在RAM中增長有用的信息,來儘量的阻止磁盤訪問。網絡

你可能認爲這很容易,可是不是。計算機的RAM包含不少東西:多線程

  • 正在執行的程序
  • 程序數據和棧
  • PostgreSQL shared buffer cache
  • 內核磁盤緩存
  • 內核

合適的調優包括在RAM中儘量多的保存數據庫信息,同時不影響操做系統的其餘區域ide

PostgreSQL Shared Buffer Cache

這裏寫圖片描述

PostgreSQL 不直接更改磁盤上的信息。相反,它請求讀數據到PostgreSQL shared buffer cache。PostgreSQL後臺來讀和寫這些塊,而且最終刷到磁盤上。

須要訪問表的後臺先在緩存中查找須要的塊。若是它們已經存在,能夠立刻繼續處理。若是沒有,一個操做系統請求被髮送去加載這些塊。這些塊從內核磁盤緩存或者直接從磁盤加載。這多是昂貴的操做。

多大算太大?

這裏寫圖片描述

你可能想,「我把所有的RAM都給PostgreSQL shared buffer cache」。然而,若是你那樣作,會沒有其餘的空間分配給內核和其餘任何要運行的程序。合適的PostgreSQL shared buffer cache 是不產生其餘不良活動的最大空間。

爲了理解不良活動,你須要去理解UNIX 操做系統怎麼管理內存。若是有足夠的內存去裝進全部的程序和數據,只須要不多的內存管理。然而,若是全部東西不能裝進內存,內核開始強制內存刷出到叫swap磁盤區域。它把最近沒有使用的內存頁移出。這個操做叫作swap pageout。Pageouts 不是問題由於它們發生在非活動時間段。糟糕的是當這些頁必須從swap返回時,意爲着移到swap的舊頁必須移入RAM。這種叫 swap pagin。這種狀況糟糕由於當頁從swap移動時,程序必須暫停直到pagein完成。

Pagein 活動能夠被系統分析工具如vmstat和sar展現,而且暗示沒有足夠的內存去有效運行。不要混淆swap pageins和ordinary pageins。它包含的頁是做爲的正常的操做系統讀取文件系統的一部分。若是你不能發現swap pageins,許多pageouts 是一個好的暗示,你也正在進行swap pageins。

緩存大小的影響

你可能好奇爲何緩存大小如此重要。首先,假設PostgreSQL shared buffer cache 足夠大去裝下整個表。這張表的重複順序掃描不須要訪問磁盤,由於全部的數據已經在緩存中了。如今假設緩存比表小一個塊大小。這個表的順序掃描須要加載全部的表數據塊進入緩存直到最後一個。當須要塊時,最老的塊被移出,這種狀況就是表的第一個塊。當另一個順序掃描發生時,第一個塊已經不在緩存中,須要把它從新裝入,這時最老的塊,也就是這個表的第二個塊被移出緩存。這又會把下一個須要的塊繼續推出去直到這個表的最後。這是一個極端的例子,可是你能夠明白減小一個塊能夠把緩存的效率從100%變爲0%。它展現了找到正確的緩存大小能夠極大的影響性能。

合適的Shared Buffer Cache大小

理想的,PostgreSQL shared buffer cache 應該是:

  • 足夠大能裝入常常訪問的表
  • 足夠小能避免swap pageins活動

記住postmaster分配全部的共享內存在它啓動的時候。這片區域保持相同的大小即便沒有一我的訪問數據庫。一些操做系統pageout不涉及共享內存,一些鎖定主存中的共享內存。鎖定共享內存是推薦的。PostgreSQL管理員指南有關於各類操做系統內核參數配置信息。

批量排序內存大小

另一個調優的參數是批量排序使用的內存大小。當排序大表或者結果集,PostgresSQL會分紅幾部分排序它們,把中間結果放到臨時文件中。這些文件合併而且從新排序直到全部的行完成排序。增長批量大小能減小臨時文件且常常能加快排序。然而,若是批量排序太大,它們會引發pageins,由於在排序時一部分批量排序pageout到swap區。這種狀況下使用更小的批量排序和更多的臨時文件是更快的。因此再次,swap pageins 指示已經分配了太多的內存。記住每一個後臺排序如ORDER BY,CREATE INDEX,或者merge join都使用這個參數。有幾個並行的排序會使用幾倍的這個內存大小。

緩存大小和排序大小

緩存大小和排序大小都影響內存使用,因此你不可能最大化一個而不影響另外一個。記住緩存大小在postmaster啓動是分配,而排序大小由正在執行的排序操做的數量決定。一般,緩存大小比排序大小更重要。然而,可預見的使用ORDER BY ,CREATE INDEX或者merge joins的肯定查詢能夠被大的批量排序大小加速。

同時,不少操做系統限制了多少共享內存能夠分配。增長這些限制須要操做系統相關的知識去從新編譯或者從新配置內核。更多的信息能夠在PostgreSQL管理員指南中找到。

做爲調優的起點,若是隻有一些大的會話,用15%的主存做爲緩存大小,2-4%做爲排序大小。若是有不少小的會話能夠調的更小。你能夠嘗試增長他們去看是否有性能提高同時沒有swap發生。若是shared buffer cache太大,你會浪費維護太多緩存的管理開銷,而且佔用其餘進程和額外的內核磁盤緩存的RAM。

一個有價值的參數是effective_cache_size。調優者使用這個參數去估計內核磁盤緩存的大小。在不固定緩存大小的內核中,這個參數能夠設置成未使用RAM的平均大小,由於這些內核使用未使用的RAM去緩存最近訪問的磁盤頁。在其餘固定大小磁盤緩存的內核中,一般應該把你的內核緩存設置成10%RAM大小。

磁盤侷限性

這裏寫圖片描述

磁盤驅動的物理特性致使了不一樣於文章中提到的其餘存儲區域的性能特色。其餘的存儲區域能夠以相同速度訪問任何字節。磁盤驅動有它本身的自旋盤和移動頭,訪問在磁頭附近的數據比距離遠的數據快的多。

移動磁頭去盤面的另外磁柱須要花費一些時間。Unix開發者知道這個特性。當排序磁盤上的大文件,他們嘗試把文件的各個條放在一塊兒。例如,假設一個文件須要10個磁盤塊。操做系統可能把1-5塊放在一個磁柱上,6-10塊放在另外磁柱上。若是這個文件須要從頭讀到未,只須要磁頭移動兩次。--一次獲取1-5塊的磁柱,一次獲取6-10塊。然而,若是文件不是順序讀,如塊1,6,2,7,3,8,4,9,5,10;須要10次磁頭移動。你能夠看到,在磁盤上,順序讀比隨機讀快不少。這是爲何若是一個表的大部份內容須要被讀,PostgreSQL偏向於順序掃描而不是索引掃描。這也凸顯了緩存的價值。

多磁盤Spindles

磁頭在數據庫活動期間移動至關多。若是產生太多的讀寫請求,驅動會變得飽和,致使性能不佳。(vmstat和sar能夠提供每一個磁盤活動量的信息)

一個磁盤飽和的解決方法是移動一些PostgreSQL的數據文件到其餘磁盤。記着,移動文件到同一磁盤的其餘文件系統沒有幫助。全部在同一磁盤的文件系統使用同一個磁頭。

經過磁盤驅動的數據庫訪問能夠經過如下幾個方法加速:
移動數據庫、表、索引
表空間容許你在不一樣的驅動上建立對象。
移動WAL
initdb -X 和符號鏈接能夠用來移動pg_xlog目錄到不一樣的磁盤驅動。不像其餘的寫操做,PostgreSQL 寫日誌必須在事務完成前刷到磁盤。緩存不能用來推遲這些寫操做。爲寫日誌使用單獨的磁盤能夠容許磁頭停留在當前日誌的磁柱而沒有移動延遲。(你可使用postgres -F 參數來阻止日誌刷到磁盤,可是一個操做系統災難須要從備份中恢復)

其餘的選項包括使用磁盤陣列,經過多個磁盤驅動加速一個文件系統。鏡像會下降數據庫寫速度,可是會加速數據庫讀,由於數據能夠從每一個驅動中得到。許多站點使用RAID1+0或RAID0+1,由於它同時提供了性能和可靠的優點。RAID5對於6個或者更多驅動來講是更快的。理論上,RAID 5將有一個由電池支持的高速緩存,所以寫入能夠以一種有效的方式刷新到磁盤,而不是在編寫文件的時候減慢應用程序的速度。

磁盤驅動緩存

現代磁盤驅動都有讀和寫緩存。讀緩存保證最近請求的磁盤塊在磁盤內存中可用。寫緩存保存寫請求直到它們能夠有效的存儲到盤面上。你可能意識到這可能產生問題--若是磁盤斷電了,當它持有的寫數據還沒寫到磁盤上怎麼辦?一些磁盤驅動和RAID控制器有後備電池寫緩存來保證數據安全,且當電源徹底恢復時把數據寫到盤面。然而,大部分驅動沒有這種特性,所以它們是不可靠的。

幸運的是,在大多數驅動你能夠關閉寫緩存。SCSI驅動默認關閉寫緩存。IDE設備寫緩存一般是打開的,可是能夠從操做系統命令關閉如hdparm -W0,sysctl hw.ata.wc=0或者scsimd。可是,一些IDE驅動雖然報告寫緩存關閉了,可是仍在使用它,這是不可靠的。沒有精確的測試很難判斷哪一個驅動在撒謊。

由於PostgreSQL每一個事務提交時使用fsync()寫WAL日誌到磁盤,而且等待寫完成。當使用寫緩存時用戶能看到巨大的性能提高。所以,爲了性能和可靠性,若是PostgreSQL能使用有後備電池的寫緩存是一個理想的方案。

SCSI vs IDE

SCSI驅動一般比IDE驅動貴不少。SCSI驅動有一個協議用來在操做系統和控制器間通訊,然而IDE驅動簡單的多且同一時刻只能接受一個請求。有標記隊列的SCSI驅動能夠接受多個請求而且從新排列它們提升效率。這是爲何當單用戶或者單文件IO時SCSI和IDE驅動有類似的性能特性,可是當多個用戶或者進程請求時SCSI比IDE性能更好。所以,SCSI更適合重負載數據庫服務器。

實際上,SCSI或IDE是惟一的方法區分兩種主要的驅動:企業驅動,爲高性能和高可靠設計。我的電腦驅動,爲最小耗費設計。這篇文章http://www.seagate.com/content/docs/pdf/whitepaper/D2c_More_than_Interface_ATA_vs_SCSI_042003.pdf,作了優秀的工做來描述在生產基於性能可靠性或者減少耗費的驅動。它是一個優秀的指導在選擇基於這些特性的驅動。

文件系統

一些操做系統支持多磁盤文件系統。在這種狀況,可能很難知道哪一個文件系統表現最好。PostgreSQL一般在傳統的Unix文件系統表現最好,像不少操做系統支持的BSD UFS/FFS等。UFS默認的8K塊大小和PostgreSQL的頁大小同樣。你能夠運行在日誌和基於日誌的文件系統,可是這些會在WAL的fsync執行期間引發額外的開銷。老的基於SvR3的文件系統變的太碎片難以有好的性能。

由於有許多文件系統能夠選擇而且沒有一個是最優的,Linux上的文件系統選擇是特別困難的:ext2不是徹底的災難安全的,ext3,XFS和JFS是基於日誌的且Reiser是對小文件優化且記錄日誌。雖然ext2比日誌文件系統塊不少,可是當要求災難恢復時ext2是不可選的。若是必須使用ext2,使用sync enabled掛載。一些人推薦使用ext3時用data=writeback掛載。

不推薦PostgreSQL使用NFS和其餘遠程文件系統。NFS和本地文件系統沒有同樣的文件系統特性,這些不一致可能引發數據可靠和災難恢復問題。

多CPU

PostgreSQL使用多進程模型,意爲着每一個數據庫鏈接擁有它本身的unix進程。所以,全部多CPU操做系統能夠經過可用的CPU來加速多數據庫鏈接。然而,若是隻有一個數據庫鏈接是活動的,它只能使用一個CPU。PostgreSQL沒有使用多線程模型從而容許一個進程使用多個CPU。

檢查點

當WAL文件充滿時,一個檢查點被執行來強制全部的髒緩存刷到磁盤,從而使日誌文件能夠循環。檢查點也會在固定的時間間隔被執行,一般是5分鐘。若是有不少的數據庫寫活動,WAL段會很塊被充滿,致使全部磁盤緩存被刷到磁盤引發系統過分的緩慢。

檢查點

檢查點應該每幾分鐘發生一次。若是在一分鐘發生幾回,性能會變差。在服務日誌中查找"checkpoint_warning"消息來決定你的檢查點是否執行太頻繁。若是30秒內檢查點執行超過一次,會出現這個消息。

減少檢查點的頻率包括增長在data/pg_xlog中WAL文件的數量。每一個文件是16 megabyte,因此它影響磁盤使用率。默認的配置使用了最小數量的日誌文件。爲了減少檢查點頻率,你須要增長這個參數:

checkpoint_segments=3

默認值是3。增長它直到檢查點幾分鐘出現一次。另一個可能出現的消息是:
LOG:XLogWrite:new log file created - consider increasing WAL_FILES
這個消息暗示postgresql.conf中的wal_files參數須要增長。

結論

幸運的是,PostgreSQL 不須要太多調優。大部分參數自動調整到最佳性能。緩存大小和排序大小是兩個參數管理員可以控制去更好的利用可用內存。磁盤訪問能夠經過多個驅動加速。其餘參數可能設置在share/postgresql.conf.sample。你能夠copy到data/postgresql.conf去實驗其餘PostgreSQL更奇異的參數。

相關文章
相關標籤/搜索