使用pg_stat_monitor擴充套件更好地理解postgresql的負載
pg_stat_monitor已經進入GA狀態。
postgres=# \dx List of installed extensions -[ RECORD 1 ]----------------------------------------------------------------------- Name | pg_stat_statements Version | 1.8 Schema | public Description | track planning and execution statistics of all SQL statements executed -[ RECORD 2 ]----------------------------------------------------------------------- Name | plpgsql Version | 1.0 Schema | pg_catalog Description | PL/pgSQL procedural language postgres=# \x Expanded display is on. postgres=# select * from pg_stat_statements; -[ RECORD 2 ]-------+-------------------------------------------------------- userid | 16384 dbid | 16608 queryid | -7945632213382375966 query | select ai_myid, imdb_id, year, title, json_column from movies_normalized_meta where ai_myid = $1 plans | 0 total_plan_time | 0 min_plan_time | 0 max_plan_time | 0 mean_plan_time | 0 stddev_plan_time | 0 calls | 61559 total_exec_time | 27326.783784999938 min_exec_time | 0.062153 max_exec_time | 268.55287599999997 mean_exec_time | 0.44391208084927075 stddev_exec_time | 2.522740928486301 rows | 61559 shared_blks_hit | 719441 shared_blks_read | 1031 shared_blks_dirtied | 0 shared_blks_written | 0 local_blks_hit | 0 local_blks_read | 0 local_blks_dirtied | 0 local_blks_written | 0 temp_blks_read | 0 temp_blks_written | 0 blk_read_time | 0 blk_write_time | 0 wal_records | 6 wal_fpi | 0 wal_bytes | 336
可以看到,這個特殊的語句,已經執行了61559次,總共消耗了27326毫秒,平均每次0.44毫秒。
如果該語句是寫資料,還可以看到生成的wal統計資訊等。這對找到哪些語句沒用在記憶體中命中而執行了物理讀寫、哪些語句可能會導致wal日誌膨脹是非常有用的。
雖然這些資料很有用,但是還可以做的更好。尤其是,很難區分問題是變好了,還是變的更糟糕了。例如,特殊的語句執行了61k次,其中60k次執行的時長是0.01毫秒,但是剩下1k次,執行的時長是1000毫秒。收集足夠的資訊,可以
雖然這些資料很棒,但它還可以更好。具體來說,很難確定問題是變得更糟還是變得更好。此外,如果執行61K次的特定查詢以 0.01ms 60K次和 1000ms 1K次執行會怎樣?需要在這裡收集足夠的資料,以便圍繞優化做出更好、更有針對性的決策。 這是pg_stat_monitor可以提供幫助的地方。
來看看pg_stat_monitor的輸出示例:
postgres=# postgres=# \x Expanded display is on. postgres=# select * from pg_stat_monitor ; -[ RECORD 1 ]-------+--------- bucket | 3 bucket_start_time | 2022-04-27 20:13:00 userid | movie_json_user datname | movie_json_test client_ip | 172.31.33.208 queryid | 82650C255980E05 top_queryid | query | select ai_myid, imdb_id, year, title, json_column from movies_normalized_meta where ai_myid = $1 comments | planid | query_plan | top_query | application_name | relations | {public.movies_normalized_meta} cmd_type | 1 cmd_type_text | SELECT elevel | 0 sqlcode | message | calls | 18636 total_exec_time | 9022.0356 min_exec_time | 0.055 max_exec_time | 60.7575 mean_exec_time | 0.4841 stddev_exec_time | 1.568 rows_retrieved | 18636 plans_calls | 0 total_plan_time | 0 min_plan_time | 0 max_plan_time | 0 mean_plan_time | 0 stddev_plan_time | 0 shared_blks_hit | 215919 shared_blks_read | 1 shared_blks_dirtied | 39 shared_blks_written | 0 local_blks_hit | 0 local_blks_read | 0 local_blks_dirtied | 0 local_blks_written | 0 temp_blks_read | 0 temp_blks_written | 0 blk_read_time | 0 blk_write_time | 0 resp_calls | {17946,629,55,6,0,0,0,0,0,0} cpu_user_time | 3168.0737 cpu_sys_time | 1673.599 wal_records | 9 wal_fpi | 0 wal_bytes | 528 state_code | 3 state | FINISHED
可以看到,新增了很多額外的資料。讓我們來比較一下:
統計資訊多出了19個列。統計資訊粒度更細了一點。
這裡,首先要介紹一些buckets的概念。什麼是桶呢?桶是時間的配置切片。除了將所有資訊都放到單個大的桶中,現在你可以將查詢狀態分開放入時間切片桶,這樣可以看到查詢效能的變化過程。預設最大的桶數是10,儲存60秒的資料。
這意味著你可以使用你喜歡的時間序列資料庫來輕鬆地查詢資料,以獲得更多的歷史分析功能。我們在內部使用這些儲存桶將資料提取到我們的查詢分析工具中,並將它們儲存在 click house 時間序列資料庫中,以提供更多的分析功能。
pg_stat_statement和pg_stat_monitor保留的資料期限是不同的:如果你想長期儲存查詢資料,可以將pg_stat_monitor和其它監控工具配置使用。
此外,你會注意到包含使用者/連線詳細資訊。許多應用程式使用同一個使用者,但有多個客戶端連線。通過客戶端IP分解資料有助於追蹤導致問題的惡意使用者或應用程式伺服器。
但我想強調一些我最感興趣的新指標和功能。對我來說,最有趣的是收集直方圖資料的能力。這使你能夠檢視查詢是否偏離正常。我們的支援工程師一直關注的關鍵問題之一是 P99 延遲如何,這有助於解決這個問題。可以在此處看到 PMM監控和管理利用這些功能:
開啟這個直方圖之後,我們可以檢視和追蹤查詢的效能是否偏離了常規。
此外,你還可以看到cpu time資訊。為什麼cpu time也很重要呢?查詢時間包含等待磁碟和等待網路資源。如果你的系統有cpu瓶頸,則耗時最長的查詢可能是問題,也可能不是問題。
最後,你可以配置pg_stat_monitor以儲存來自先前執行的查詢的解釋計劃。當計劃隨著時間而改變時,這非常有用,如果你正試圖重現一兩個小時前發生的事情。
獲得額外的洞察能力和了解工作負載至關重要,而pg_stat_monitor可以幫助做到這兩點。 pg_stat_monitor支援端到端可追溯性、跨可配置時間視窗的聚合統計資訊和查詢執行時間,PMM將這一點視覺化並讓使用者更深入地瞭解 PostgreSQL 行為。