Amplitude是一家數據分析公司,目標是提供易于使用的交互式產品分析,希望每個人都可以從中找到他們產品問題的答案。為了提供良好的用戶體驗,Amplitude需要快速提供這些答案。所以,當他們的一個客戶抱怨在Amplitude UI中加載事件屬性下拉時間特別長的時候,Amplitude開始深入研究這個問題。
通過跟蹤不同級別的延遲,他們認為一個特定的PostgreSQL查詢需要20秒才能完成。 這對他們來說是值得思考的,因為兩個表都在連接列上有索引。
▲Slow Query
這個查詢的PostgreSQL執行計劃是奇怪的。即使兩個表都有索引,PostgreSQL也決定在大表上進行順序掃描,這是查詢時間的大部分來源。
▲慢查詢執行計劃
Amplitude最初懷疑這可能是由于碎片化。但是在檢查數據后,意識到這個表只是附加的,這個表上沒有多少刪除。由于使用真空回收空間在這里不是很有幫助,所以Amplitude開始探索其他解決方案。接下來,Amplitude嘗試了對另一個客戶進行相同查詢,但是響應時間很好。令我驚訝的是,查詢執行計劃看起來完全不同!
有趣的是,應用程序A只能訪問比應用程序B多10倍的數據,但響應時間卻延長了3000倍。
要查看PostgreSQL在選擇散列連接之前考慮的替代查詢計劃,Amplitude禁用散列連接并重新進行了該查詢。
▲慢查詢的可替代執行計劃
使用嵌套循環代替散列連接時,相同的查詢速度提高了50倍。那么為什么PostgreSQL選擇一個更糟糕的A計劃呢?
仔細查看兩個計劃的預估成本和實際運行時間,實際運行時間與估計成本的比率是非常不同的。 造成這種差異的主要原因是順序掃描成本估算,PostgreSQL估計順序掃描比4000+索引掃描更好,但實際上索引掃描速度要快50倍。
這主要與'random_page_cost'和'seq_page_cost'配置選項相關。對于'random_page_cost','seq_page_cost'分別默認的PostgreSQL值為4和1,這些值是針對硬盤設置的,隨機存取磁盤比順序存取要貴。然而,這些成本對于使用固態驅動器的gp2 EBS卷部署是不準確的。對于這種部署方式,隨機和順序訪問幾乎是一樣的。
Amplitude將“random_page_cost”更改為1并重試了查詢。這一次,PostgreSQL使用了一個嵌套循環,查詢速度提高了50倍。改變之后,我們也注意到PostgreSQL的最大響應時間顯著下降。
▲總體慢查詢性能顯著提高
如果你正在使用SSD并以默認配置運行PostgreSQL,建議嘗試調整random_page_cost&seq_page_cost,可能會帶來一些巨大的性能改進。
有沒有其他的參數調整給你帶來過巨大收益?歡迎留在評論里。