執行SQL語句時,如果出現慢SQL或SQL占用系統內存的情況,需進行具體查詢分析。

查詢慢SQL

查詢慢SQL語句分為以下兩種情況:
  • 查看歷史慢SQL語句:
    通過觀察pg_stat_statements視圖,執行時間較長的SQL語句。
    SELECT total_time / calls AS  avg, query 
    FROM pg_stat_statements ORDER BY avg DESC LIMIT 10;
  • 查看當前慢SQL語句。
    查詢執行時間超過1秒的SQL:
    select * from pg_stat_activity where state<>'idle' and now()-query_start > interval '1 s' order by query_start ;

使用EXPLAIN查詢SQL計劃

通過使用EXPLAIN查詢SQL計劃,可分析SQL的快慢或資源占用情況。

使用EXPLAIN執行以下語句,可獲得SQL的查詢計劃。具體語法示例如下:
EXPLAIN [ ( option [, ...] ) ] statement
EXPLAIN [ ANALYZE ] [ VERBOSE ] statement

where option can be one of:

    ANALYZE [ boolean ]
    VERBOSE [ boolean ]
    COSTS [ boolean ]
    BUFFERS [ boolean ]
    FORMAT { TEXT | XML | JSON | YAML }
上述示例對應的命令參數選項含義如下:
參數 說明
ANALYZE 會實際執行SQL,并獲得相應的查詢計劃,默認為FALSE。如果優化一些修改數據的SQL 需要真實的執行但是不能影響現有的數據,可以放在一個事務中,分析完成后可以直接回滾。
VERBOSE 會顯示查詢計劃的附加信息,默認為FALSE。附加信息包括查詢計劃中每個節點輸出的列(Output),表的SCHEMA信息,函數的SCHEMA 信息,表達式中列所屬表的別名,被觸發的觸發器名稱等。
COSTS 會顯示每個計劃節點的預估啟動代價(找到第一個符合條件的結果的代價)和總代價,以及預估行數和每行寬度,默認為TRUE。
BUFFERS 會顯示關于緩存的使用信息,默認為FALSE。該參數只能與ANALYZE 參數一起使用。緩沖區信息包括共享塊(常規表或者索引塊)、本地塊(臨時表或者索引塊)和臨時塊(排序或者哈希等涉及到的短期存在的數據塊)的命中塊數,更新塊數,擠出塊數。
FORMAT 指定輸出格式,默認為TEXT。各個格式輸出的內容都是相同的,其中XML | JSON | YAML更有利于您通過程序解析SQL語句的查詢計劃。

視圖分析

可以通過觀察視圖pg_stat_statementspolar_stat_sql進行分析SQL執行需占用的資源情況,這兩個視圖需創建相關插件,并打開開關。
CREATE EXTENSION pg_stat_statements;
CREATE EXTENSION polar_stat_sql;

postgres=# alter system set polar_stat_sql.enable_stat=on;
ALTER SYSTEM
postgres=# alter system set polar_stat_sql.enable_qps_monitor=on;
ALTER SYSTEM
postgres=# select pg_reload_conf();
 pg_reload_conf 
----------------
 t
(1 row)
  • pg_stat_statements視圖說明請參見pg_stat_statements
  • polar_stat_sql視圖說明。

    sql級別監控視圖信息包含4個部分內容:

    • 執行計劃節點統計信息(掃描計劃節點、join計劃節點、聚集計劃節點、排序計劃節點、hash計劃節點)。
    • 收集sql級別的CPU運行時間(分為系統態和用戶態)、IO(讀寫字節數)、memory(請求頁數,交換頁數)、ipc(ipc message接受量和請求量)、CPU上下文切換(分為自愿切換和非自愿)。
    • SQL的各個執行階段耗時統計,包括parse時間、analyze時間、rewrite時間、執行計劃生成時間、執行時間。
    • latch和鎖信息統計。
    polar_stat_sql視圖是記錄的累計數據,在執行sql之前需進行清空。
    postgres=# select polar_stat_sql_reset();
     polar_stat_sql_reset 
    ----------------------
     
    (1 row)