PG類數據庫優化之穩定關鍵SQL執行速度
大家用Oracle數據庫的時候,根本不需要過多的去考慮數據庫物理結構以及OS物理結構方面的優化。因為Oracle把一切都幫我們做好了,只需要交給Oracle足夠容量,足夠能力的物理資源就一切OK了。不過作為三十年前就開始使用Oracle數據庫的我們這一代DBA,還是經歷過很多這樣的優化案例的。在那個年代,曾經通過底層存儲的重新條帶化設計,讓一套IO負載極高的數據庫系統的批處理作業性能提高數倍。
現在我們如果不使用Oracle數據庫了,我們要把應用從Oracle遷移到國產數據庫上了,那么這些老手藝可能又有些作用了。不過與那個時代不同的是,現在硬件的能力已經百倍的提升了,存儲系統的全局IO打散能力也成為了標配,因此再也不需要像我在二十多年前那樣為了一點點的IOPS去精打細算了。
今天這個話題雖然我已經把討論范圍縮小到了物理結構優化上,不過還是太大,我不大可能在一個一千多字的文章里把所有的問題都講清楚,因此我們今天還是縮小到一個比較小的話題上吧,那就是如何通過底層物理結構的優化讓關鍵業務系統在PG類數據庫上平穩運行。這里講的是PG類數據,除了社區版的PG外,還有大量基于PG的開源、國產數據庫產品,包括華為的GAUSSDB系列,瀚高、金倉、神通、優炫、亞信ANTDB、中國移動磐維等,都是PG類數據庫。甚至今天我討論的部分內容對于MYSQL、達夢、SQL SERVER等沒有使用DIO的數據庫也是有一定作用的。
最近我經常聽說某些客戶把數據庫從Oracle遷移到國產數據庫上后,一些關鍵業務忽快忽慢,檢查執行計劃也沒啥問題,操作系統層面也沒有明顯的瓶頸或者慢的因素。實際上這與數據庫沒有使用DIO有很大的關系。對于沒有使用DIO的系統,當數據沒有在DB CACHE中命中的時候,會產生物理讀。不過這個物理讀并不一定真正的從物理存儲介質上讀取,如果數據在LINUX的OS CACHE里,那么可以直接從CACHE中獲取,這種物理讀是很快的,如果OS CACHE沒有命中,那么就只能真正的從物理存儲介質中去讀取了,相對于直接從內存中讀取,這種物理讀是較慢的。因為OS CACHE沒辦法按照我們的數據庫訪問需求去緩沖數據,因此OS CACHE的目的性并不強。這種忽快忽慢大多數集中在讀操作上的,不過有時候寫也會出現抖動,那是因為OS層面的的后臺進程、檢查點以及WAL或者文件寫的FSYNC都會讓OS產生一個抖動,從而對事務提交或者索引更新產生性能影響。在并發量較大、存在熱點寫數據的應用中,就很可能會產生一定的影響了。
我們無法去改變上面所說的DOUBLE BUFFERING的問題,這只能通過國產數據庫廠商的努力在自己的數據庫產品里全面引入DIO來解決了。實際上目前為止只有Oracle能夠比較好的把控DIO,除此之外,哪怕是SQL SERVER這種老牌的商用數據庫,雖然可以支持DIO,但是也不建議啟用DIO。
可能有些朋友覺得偶爾出現幾條SQL執行變慢沒啥所謂,這可能和你看到的應用場景有關。如果是股票交易或者銀行交易出現了某個時段幾百筆交易延時異常,那么對于這個企業來說就是運維事故了。如果一條核心交易的SQL,平時執行只需要5毫秒,抖動時就可能變成三四十毫秒,現在網聯對金融機構的交易超時監控十分嚴格,一次這樣的抖動足以產生一次告警了。
要想避免此類抖動,必須在物理結構上做好優化。我今天提出幾點優化的建議。首先是對底層存儲的優化,如果不是使用集中式存儲,那么還需要考慮512E和4KN等現代磁盤扇區大小的問題以及相關的對齊問題。今天篇幅有限,就不展開討論了,有興趣的朋友可以參考我以前寫過的一篇文章《原來ADVANCED FORMAT HDD已經普及了》(https://mp.weixin.qq.com/s?__biz=MzA5MzQxNjk1NQ==&mid=2647848163&idx=1&sn=0f27f69e5d337a3873d6f3cdaa841a24&chksm=88786877bf0fe161178bed2cc05c2db84265ae3356ade0847e81b2e331e299d580c89dc31c9f&token=1445168299&lang=zh_CN#rd)。
除此之外,怕抖動的核心交易系統盡可能使用比較快的存儲介質,比如NVME SSD,盡可能降低平均IO延時是從根本上降低IO抖動帶來的問題的最便宜的方法,不要覺得SSD很貴,實際上在這里多花點錢可以在其他地方少花更多的錢。
第二個需要關注的就是存儲的規劃,通過使用獨立的表空間和文件系統,讓相互影響,可能導致運行毛刺的應用之間的沖突盡可能地減少。如果系統不重要,或者抖動無所謂,那么不需要做這方面的優化,而如果這個系統是十分關鍵的核心系統,那么在這方面做再多的工作都是值得的。在二十多年前,搞Oracle 7的時候,這些手段我也都用過。
對于寫入十分重的系統,WAL盡可能獨立存儲于高性能的獨立磁盤上,避免與其他讀寫IO沖突。小型熱表也可以存儲于獨立的表空間里。相對靜態,但是會大規模掃描的冷數據獨立存儲,訪問十分頻繁的表的索引與數據分開等都是可以采取的IO隔離手段。具體要根據業務的特點去做規劃。前面討論的都是從本地磁盤的角度去考慮的,實際上目前大多數系統使用集中式存儲,很多IO延時穩定性的問題可能要考慮后端存儲的規劃與優化,大家要注意這個問題。后端存儲分過來的盤和實際的物理盤是不同的。
第三個需要關注的問題是OS層面針對性的優化,這一點大家可以參考我的另外一篇文章《Postgresql數據庫優化上該考慮些什么》(https://mp.weixin.qq.com/s?__biz=MzA5MzQxNjk1NQ==&mid=2647849429&idx=1&sn=2776253a04b780d090bfe7a03784345c&chksm=88786541bf0fec573182c704e41c0adddc9d96ee0af694cea263d685ce51fb3f9b4aa7700f52&token=1445168299&lang=zh_CN#rd),這里我就不重復介紹了。
第四個要考慮的是SHARED_BUFFERS的設置,如果我們在運行一個十分關鍵的核心交易系統,那么建議還是配置大一點的物理內存,并將SHARED BUFFFERS設置的足夠大,盡可能地讓熱點數據都能夠長期緩沖在數據庫緩沖區里,從而穩定關鍵業務地運行效率。但是業務系統十分復雜,是不是也會產生一些對大型冷數據的掃描操作。這些操作盡可能地放到只讀備機上去做,而不要影響核心業務系統的數據庫緩沖。一種更好的設計是將這些可能對核心交易產生影響的數據從核心數據庫中剝離出去,另外建個庫,那樣的話對核心交易的影響就小多了。