MON_GET_PKG_CACHE_STMT 表函數
還可以使用 MON_GET_PKG_CACHE_STMT 表函數來查詢當前 PACKAGE CACHE 中 SQL 語句(包括動態 SQL 和靜態 SQL)的執行信息,這是一個非常強大的工具,能夠返回非常多的信息包括各種時間信息,例如語句執行過程總的等待時間、等待鎖的時間、等待排序的時間等等。當發現語句執行時間長時,可以用這個表函數來分析時間的分布情況,是消耗在等待上還是讀數據上或者其他因素。查詢語句如清單 2 所示,結果在圖 4 中。清單 2 的語句並不是直接查詢表函數來顯示結果,而是計算了每個語句的平均執行時間,以及各項等待時間在總的執行時間的百分比,這樣結果更直觀一些,但需要注意的是示例查詢中只選擇了一部分字段,還可以根據情況增加更多的字段,例如增加 TOTAL_EXTENDED_LATCH_WAIT_TIME 來查看 LATCH 等待時間。
清單 2. 使用 MON_GET_PKG_CACHE_STMT 表函數
1
2
3
4
5
6
7
8
9
10
11
12
|
db2 +w "SELECT MEMBER,
NUM_EXECUTIONS,
STMT_EXEC_TIME,
decimal((TOTAL_ACT_WAIT_TIME / double(STMT_EXEC_TIME)) * 100, 5, 2) as pct_wait,
decimal((POOL_READ_TIME / double(STMT_EXEC_TIME)) * 100, 5, 2) as pct_read,
decimal((LOCK_WAIT_TIME/double(STMT_EXEC_TIME)) * 100, 5, 2) as pct_lock,
decimal((LOG_DISK_WAIT_TIME / double(STMT_EXEC_TIME)) * 100, 5, 2) as pct_log,
decimal((TOTAL_SECTION_SORT_TIME / double(STMT_EXEC_TIME)) * 100, 5, 2) as pct_sort,
CAST(FLOAT(STMT_EXEC_TIME)/FLOAT(NUM_EXECUTIONS) as decimal(10,3)) as AVG_EXEC_TIME,
VARCHAR(STMT_TEXT,500) AS STMT_TEXT
FROM TABLE(MON_GET_PKG_CACHE_STMT(NULL,NULL,NULL,-2))
WHERE NUM_EXECUTIONS >1 and STMT_EXEC_TIME>0"
|
圖 4. MON_GET_PKG_CACHE_STMT 查詢結果
在圖 4 中可以看到,這些語句的 AVG_EXEC_TIME(平均執行時間)在 2~6 秒不等,其中有 5 條語句(with 開頭的語句)的 PCT_WAIT 在 95%以上,也就是說這 5 條的執行時間花在了等待上,但是等待的不是 READ、Lock、寫事務日志或者排序,而且別的原因。在清單 2 語句的基礎上繼續增加查詢字段,會發現這些語句是在等待 LATCH 上。另外 5 條語句都是調用存儲過程的,從這里看不出來時間分布。
結合多種方式獲取的 SQL 語句來看,有多條 SQL 語句執行時間為 3~6 秒,對於 OLTP 系統這已經是非常慢了,在並發量稍大的情況就會出現 ACTIVE SESSION 數量高。這些慢的語句中有一部分是因為 LATCH 等待,還有一部分沒有等待。這時候可以開始着手優化 SQL,作者也確實這樣做了,先是快速的通過創建索引解決了幾個有全表掃描的 SQL,然后又去梳理並且嘗試優化那些很長且邏輯復雜的 SQL 語句。但是,那些邏輯復雜的長 SQL 並不是最近才上線的啊,會不會以前也是這么慢,最近沒有應用程序變更啊(也沒有數據庫變更),現在努力的方向不對吧。。。及時的打住,進行思考。
快速排除法
可以快速的排除數據庫服務器資源問題,CPU 利用率在正常范圍內,操作系統內存使用量正常。根據 db2top 結果(如圖 1)快速的判斷數據庫緩沖池命中率(HitRatio)正常,沒有 LOCK WAIT,從右下角四個參數 AvgPRdTime(Average Physical Read time),AvgDRdTime(Average Direct Read Time),AvgPWrTime(Average Physical Write time)和 AvgDWrTime(Average Direct Write time)可以判斷 I/O 正常。注意到 Deadlocks 為 218,但這是一個累計值而且不會影響性能,還注意到有 SortOvf(Sort Overflow)為 10,有點兒高但考慮到應用程序的 SQL 語句用了較多的排序,所以有一些排序溢出應該不是主要問題。