在Windows上調優(yōu)DB2數據庫的八個簡單步驟
概述
為了更好地診斷性能問題,本文討論了一個有條理的過程,幫助確定數據庫是否存在性能問題,并制定補救措施。當 DB2或電子商務應用程序的性能未達到預期目標時,整個組織和財務底線都可能受到影響。
本文旨在指導 DBA 在 Windows上定義和診斷 DB2 的性能問題。本文涵蓋的內容如下:
- 使用 Windows 工具收集的信息
- 使用 DB2 工具收集的信息
- 問題的調查和解決
假設
本文假定讀者對數據庫、SQL 和 DB2 LUW 已有基本的了解。對 UNIX的性能調優(yōu)和監(jiān)控有基本的了解可能會對您有所幫助。
性能問題以及它們與系統資源的關聯
性能問題涵蓋廣泛的場景:
- SQL 查詢執(zhí)行速度比預期慢
- 工作負載或批處理作業(yè)沒有在預期時間內完成,或事務率和吞吐量在一段時間內逐步下降
- 系統整體速度下降
在大多數情況下,出現性能問題是因為系統資源的使用不當或 CPU、IO 和內存等資源的過度使用,這往往揭示了這些系統資源中的瓶頸。在經過適當調優(yōu)的環(huán)境中,系統資源會得到***使用,不會過度依賴其中任何一種資源。
診斷性能問題的***個步驟是,識別所有資源瓶頸。Windows 提供了一些可以幫助識別這些瓶頸的工具。
CPU 瓶頸
如果系統上有一個或多個 CPU 一直顯示 90% 以上的利用率,這通常意味著系統存在 CPU 瓶頸。任務管理器可以幫助您找出系統是否存在 CPU 瓶頸。其他工具(如 perfmon.exe 和資源監(jiān)視器)會顯示 CPU 利用率,也可以幫助識別 CPU 瓶頸。
內存瓶頸
內存瓶頸并不是很常見,這主要是因為數據庫的堆和參數通常是根據可用內存進行配置的。但是,如果在 perfmon 和資源監(jiān)視器中看到非常低的可用內存,那么這可能表示存在內存瓶頸。有時候,在使用 STMM 時,系統上的可用內存可能會非常低,但這并不總是意味著該系統存在內存瓶頸。
網絡瓶頸
如果在資源監(jiān)視器中看到非常高的網絡利用率,那么這可能表示存在網絡瓶頸。資源監(jiān)視器以百分比的形式顯示網絡利用率,這有助于快速識別網絡瓶頸。如果資源監(jiān)視器顯示網絡利用率在 80% 以上,這通常表示存在網絡瓶頸。
I/O 瓶頸
如果系統上有一個或多個磁盤在 90% 以上的時間一直處于忙碌狀態(tài),或磁盤隊列長度不斷顯示較高的數量,這通常意味著系統存在 I/O 磁盤瓶頸。Windows工具(如資源監(jiān)視器和 perfmon)可以幫助識別 I/O 瓶頸。任務管理器確實可以顯示 I/O 活動,但資源監(jiān)視器和 perfmon 可以顯示每個磁盤的 I/O 詳細信息,還可以顯示活動時間的百分比,這有助于識別任何特定的磁盤上是否存在瓶頸。
有多種 Windows 工具可以幫助確定系統是否有一個或多個資源瓶頸。#p#
步驟 1:使用 Window 工具識別瓶頸
任務管理器
任務管理器是獲得有關整個系統的使用情況的信息的最快方式。例如,圖 2 是任務管理器的 Processes 選項卡的屏幕截圖,其中的列提供每個進程的 CPU、內存、I/O 統計信息 (View > Select Columns)。任務管理器很好地總結了 CPU、I/O、內存和網絡利用率。任務管理器也提供了進程的詳細信息,幫助找出哪些進程正在消耗最多的 CPU,哪些進程正在執(zhí)行最多的 I/O 等。
如果任務管理器顯示,整體 CPU 利用率一直超過 90%,那么這是存在 CPU 瓶頸的一種跡象。任務管理器也在 Performance 選項卡顯示每個 CPU 活動。如果其中任何一個 CPU 的利用率一直接近 100%,這可能也意味著存在一個 CPU 瓶頸。通常情況下,這意味著數據庫中的工作負載是單線程的,無法利用系統上的所有可用 CPU。圖 1 是單線程應用程序運行的一個示例。即使只有一個 CPU 處于忙碌狀態(tài),沒有使用其他 CPU,它仍然是一個 CPU 瓶頸。
任務管理器還顯示每一個進程從磁盤上讀出/寫入的數據量的詳細信息。該信息本身非常有用,但它沒有顯示每個磁盤的利用率百分比。這使得用戶很難僅通過任務管理器來斷定系統是否存在 I/O 瓶頸。
圖 1. 任務管理器 — 單線程工作負載示例
圖 2. 任務管理器顯示了內存使用率***的進程
資源監(jiān)視器
資源監(jiān)視器是在 Windows 2008 和 Windows 7 上提供的另一個 Windows 工具。它提供有關 I/O、CPU、內存和網絡使用情況的詳細信息。該工具顯示了在您的系統上運行的所有進程的實時信息,并提供了根據用戶要求篩選數據的能力。可以基于內存、CPU、磁盤和網絡使用情況做到這一點。Overview 選項卡顯示了整個系統的活動,并提供了系統中瓶頸的快照。I/O 和網絡使用情況以可用帶寬的利用率百分比的形式顯示。這有助于識別系統是否存在 I/O 瓶頸或網絡瓶頸,從任務管理器中不可能確認這一點。此外,資源監(jiān)視器顯示了每個磁盤的磁盤隊列長度,對于確定磁盤是否有足夠的帶寬來解決系統的 I/O 需求而言,這很有用。
圖 3. 資源監(jiān)視器
圖 4. 資源監(jiān)視器 DB2 磁盤活動
perfmon
雖然任務管理器和資源監(jiān)視器對于確定系統活動都是很好用的工具,但不能使用它們將系統活動記錄在日志中,以供日后分析。Perfmon 工具可以將系統活動記錄在日志文件中。這提供了靈活性,讓管理員和 DBA 可以在一天中的不同時間收集 perfmon 數據,并在以后使用它們進行分析。Windows 附帶的 perfmon 工具可用于捕獲性能數據和資源使用情況的統計數據。對于許多類型的問題調查,了解如何設置和捕獲 perfmon 日志都很關鍵。在監(jiān)視 I/O 時需要注意的是:需要通過運行 diskperf -y (-ye 表示帶區(qū)集)啟用磁盤計數器,然后重新啟動。在 Windows 2008 或 Windows 7 上,需要運行 perfmon,將活動捕獲到日志文件中:
- 在命令提示符下運行 perfmon。
- 從左面的框架中選中 Performance Monitor。
- 右鍵單擊它,并選擇 New > Data Collector set。創(chuàng)建一個合適的名稱,并單擊 Next。
- 提供一個將會保存日志的目錄名稱。
- Data Collector set 出現在左邊的框架中。在左邊的框架選中 Data Collector Set > User Defined,并選中您在步驟 4 所選擇的名稱。它的狀態(tài)應該是已停止,因為我們希望在收集開始之前,先添加所需的計數器。
- 右鍵單擊已定義的 Data collector set 并選擇 New > Data Collector。提供一個名稱,并選中 Performance counter data collector,然后單擊 Next。選擇采樣頻率并增加性能計數器。Perfmon 工具提供了很多計數器來監(jiān)視多種參數,下面介紹最有用的幾個計數器。這對于收集數據是一個很好的出發(fā)點。根據具體的要求和情況,用戶可以收集和監(jiān)視其他計數器。
7.一旦完成了如下圖所示的性能計數器選擇,就可以收集所需的時間間隔的數據??梢允褂盟x擇的數據收集器集的屬性部分對此進行修改。為所選擇的計數器收集的數據可以保存為表或電子表格的格式。在 File 選項卡下的屬性部分,可以指定輸出的格式。
圖 5. perfmon 性能計數器
8.一旦準備好進行數據收集,就可以啟動您的工作負載或查詢,立即通過單擊選定的數據收集器集上的 Start 開始數據收集。
完成查詢/工作負載后,停止監(jiān)視數據收集,并檢查收集到的數據。#p#
選擇正確的診斷工具
對于普通的監(jiān)視,perfmon 是一個很好用的工具。還可以保存其日志,以便更輕松地比較系統在按預期工作時和系統有性能問題時的系統活動。這往往可以為手頭上的問題提供有價值的線索。然而,快速查看任務管理器和資源監(jiān)視器的數據有時也可以幫助實時查找系統中的瓶頸。一旦確定了瓶頸,就可以采取相應的措施來消除瓶頸。
步驟 2:I/O 瓶頸 — 詳細研究
如果 perfmon 顯示有一個或多個磁盤的磁盤時間在 80% 以上,或資源監(jiān)視器顯示有一個或多個磁盤上的活動時間在 80% 以上,那么這通常意味著系統中存在一個 I/O 瓶頸??梢詮?perfmon 或資源監(jiān)視器確定具有很高利用率的一個或多個磁盤。一旦確定了大量使用的磁盤,就可以找出放置在磁盤上的內容。
是否有任何 DB2 表空間容器放置在磁盤上?
db2 list tablespace containers for <tbsid> |
對數據庫中的所有表空間重復此命令。
或者,DB2 日志文件是否被放置在大量使用的磁盤上?
db2 get db cfg for <dbname> |
搜索 newlogpath 數據庫配置參數。
或者,這些磁盤是否包含實用程序文件,比如備份目標或加載文件?查看已執(zhí)行的備份/負載命令。根據大量使用的磁盤上的內容,解決方案也會有所不同。
表空間容器上的磁盤瓶頸
如果將大量使用的磁盤分配到表空間容器,那么請找出表空間中的對象。如果表空間對應于某個數據表空間,那么請找出在表空間中創(chuàng)建的表。
db2 select tabname from syscat.tables where tbspaceid = <hot tablespace id> |
從 MON_GET_TABLE 表函數中找出最活躍的表。下面的查詢將列出具有最多行讀取的表。
清單 1. 表空間中最活躍的表
- db2 "select varchar(tabschema,20) as tabschema, varchar(tabname,20) as tabname,
- table_scans, sum(rows_read) as total_rows_read,
- sum(rows_inserted) as total_rows_inserted,
- sum(rows_updated) as total_rows_updated,
- sum(rows_deleted) as total_rows_deleted
- FROM TABLE(MON_GET_TABLE('','',-2)) AS t
- WHERE TBSP_ID = hot tablespace id
- GROUP BY tabschema, tabname
- ORDER BY total_rows_read DESC"
注意:MON_GET_TABLE 函數提供了許多有用的信息。它在表上跟蹤表掃描的數量。如果表掃描較多,那么可能意味著該表沒有適當的索引,或者查詢沒有使用表上現有的索引。
一旦確定了活躍的表,就可以使用 MON_GET_PKG_CACHE_STMT 表函數輕松找出表上執(zhí)行的 SQL 語句。
清單 2. 找出給定表上的查詢
- db2 "select section_type, executable_id, package_name,num_executions,
- char(stmt_text, 100)
- from table (MON_GET_PKG_CACHE_STMT ( 'D', NULL, NULL, -2)) as T
- where stmt_text like '%hot table name%' "
通過這種方式,很容易找出活躍的表上導致大量讀取/寫入操作的 SQL 語句。使用 Design Advisor 確定 SQL 語句是否使用了表上正確的索引。如果表中有適當的指標,但沒有用到這些指標,那么請檢查表上的統計信息是否是***信息。不正確或過時的統計信息可能會導致優(yōu)化器選擇一個次優(yōu)的訪問計劃。
臨時表空間上的磁盤瓶頸
如果將大量使用的磁盤分配到臨時表空間,這表示數據庫上有大量排序活動。高水平的臨時表空間 I/O 活動往往與結果集較大或有大量排序的大查詢一起出現。在這種情況下,需要確定是否有大量排序溢出到磁盤。 MON_GET_PKG_CACHE_STMT 可以提供造成排序溢出的 SQL 語句。
清單 3. 有大量排序活動的查詢
- db2 "select section_type, package_name,num_executions, total_sorts, sort_overflows,
- char(stmt_text, 100)
- from table (MON_GET_PKG_CACHE_STMT ( 'D', NULL, NULL, -2)) as T
- where sort_overflows > 1
- order by sort_overflows desc"
如果有太多排序溢出,那么請檢查 SORTHEAP 或 SHEAPTHRES 配置參數是否被設置為較低的值。如果排序的相關參數得到正確設置,那么請確定是否有可能通過創(chuàng)建索引來避免出現大量排序。對排序量較大的查詢使用 Design Advisor,查看是否能夠通過創(chuàng)建額外的索引來避免或減少排序。
事務日志上的磁盤瓶頸
在 OLTP 環(huán)境中,事務日志的性能是非常敏感的。MON_GET_TRANSACTION_LOG 表函數提供了有關事務日志的詳細活動。
清單 4. 事務日志活動
- db2 "select log_reads, log_read_time, log_write, log_write_time, num_log_buffer_full,
- num_log_data_found_in_buffer
- from table(MON_GET_TRANSACTION_LOG(-1)) as T "
num_log_buffer_full 顯示了在將新的日志寫入緩沖區(qū)之前,日志緩沖區(qū)被充滿并且必須刷新到磁盤的次數。如果這個數字在一段時間內一直在增加,則意味著日志緩沖區(qū)對于數據庫上的工作負載而言過小。增大 LOGBUFSZ 數據庫參數值有助于提高日志性能,并減少事務日志磁盤上的 I/O。
num_log_data_found_in_buffer 顯示了代理從緩沖區(qū)中讀取日志數據的次數。從緩沖區(qū)中讀取日志數據優(yōu)于從磁盤讀取日志數據,因為后者較慢。可以結合使用此元素和 num_log_read_io element,以確定是否需要進一步增大 LOGBUFSZ 數據庫配置參數。
步驟 3:CPU 瓶頸 — 詳細研究
如果 perfmon 或資源監(jiān)視器顯示有一個或多個 CPU 的使用率超過 90%,那么這通常意味著系統存在 CPU 瓶頸。與 I/O 瓶頸一樣,***個步驟是識別消耗大量 CPU 的數據庫操作。通常情況下,已知道有一些數據庫操作會消耗大量的 CPU:
- 語句編譯
- LOAD、BACKUP、runstats 等實用工具
- 大量排序活動
要確定在查詢編譯中是否花費了大量 CPU,請查詢 MON_GET_WORKLOAD 表函數。
清單 5. 在不同活動中花費的 CPU 時間
- db2 "select varchar(workload_name,30) as workload_name,
- sum(total_cpu_time),sum(total_compile_proc_time),
- sum(act_rqsts_total), sum(total_compilations),
- sum(total_act_time), sum(pkg_cache_inserts),
- sum(pkg_cache_lookups)
- from TABLE(MON_GET_WORKLOAD('',-2)) as T
- group by workload_name"
如果 compile_proc_time 高于 5-10% 的 total_cpu_time,并且 pkg_cache_inserts/pkg_cache_lookups 高于 4-5%,則數據庫在語句編譯上花費了太多的時間。這可能是因為查詢被重復編譯,或者是因為包緩存過小,查詢必須遷離到其他地方,以便為新的查詢騰出空間。如果應用程序使用字符串文本而不是參數標記符,則會重復編譯 SQL 語句。在 DB2 9.7 和 10.1 中,DB2 提供了一個數據庫配置參數 STMT_CONC(語句集中器)。當啟用該參數時,語句集中器會修改動態(tài)語句,以便允許共享更多的包緩存條目,并減少語句編譯。
要找出造成高 CPU 利用率的所有實用工具,請查詢 MON_GET_WORKLOAD 表函數。返回的指標展示了用于已提交的請求的所有指標的匯總,這些請求是由映射到已識別工作負載對象的連接提交的。在請求的執(zhí)行過程中,指標在工作單元邊界上或定期被匯總到一個工作負載。由該表函數報告的值,反映系統在最近一次匯總時的當前狀態(tài)。指標是嚴格遞增的值。為了確定在某時間間隔花費在 LOAD 和 reorg 等實用工具中的時間,可以使用 MON_GET_WORKLOAD 查詢在時間間隔的開始和結束時使用的指標,并計算其差異。
清單 6. 在 LOAD 和 runstat 實用工具中花費的 CPU 時間
- db2 "select varchar(workload_name,30) as workload_name,
- sum(total_loads), sum(total_load_proc_time),
- sum(total_runstats), sum(total_runstats_proc_time)
- from TABLE(MON_GET_WORKLOAD('',-2)) as T
- group by workload_name"
LOAD 等實用工具旨在充分利用可用資源,***限度地提高性能。如果這些實用工具占用了比預期多的 CPU,那么可以通過設置 util_impact_limit 數據庫配置參數對實用程序進行節(jié)流。另一個占用大量 CPU 的數據庫操作是 sort。正如在 I/O 瓶頸部分所介紹的,找出執(zhí)行最多排序活動的查詢,并使用 Design Advisor 確定是否可通過創(chuàng)建額外的索引來避免排序。
步驟 4:內存瓶頸
內存瓶頸并不是很常見,主要是因為數據庫的堆和參數可以根據可用內存進行設置。大多數 DB2?? 堆是自動的,并基于可用內存提供分配值。STMM 在利用可用內存和將內存分配給最需要內存的堆這兩方面做得很好。但是,在不使用 STMM 的情況下,有可能存在內存使用不當的情況,如果內存分配得過多(也就是說,分配值高于可用內存),則有可能導致大量分頁活動。如果 Perfmon 或資源監(jiān)視器顯示了許多分頁活動,這通常是因為分配給不同堆的內存已超過實際內存。在這種情況下,***是打開 STMM,讓 DB2 調優(yōu)緩沖池、排序堆和其他堆的內存。
步驟 5:網絡瓶頸
出現網絡瓶頸的原因通常是存在大量四處移動的數據(比如非常大的結果集和客戶端負載等),或者操縱 LOB 的應用程序位于客戶端-服務器架構中。MON_DB_SUMMARY 管理視圖很好地說明了等待不同的資源所花費的時間。NETWORK_WAIT_TIME_PERCENT 字段提供了等待網絡響應的時間百分比。通常情況下,等待網絡所花費的時間應該小于 1%。如果該值高出幾個百分點,并且 perfmon 和資源監(jiān)視器顯示網絡帶寬在大量被占用,那么系統可能遇到了網絡瓶頸。在這種情況下,應用程序可以將一些應用程序邏輯以存儲過程或者 UDF 的形式移動到服務器。在客戶端負載的情況下,可以將負載拆分為更小的部分,在不同的時間執(zhí)行它們,而不是一次全部加載它們,這樣做可以減少網絡流量。
步驟 6:鎖定問題
如果系統沒有任何資源瓶頸,但性能仍然較差,這可能是因為鎖定問題。MON_DB_SUMMARY 管理視圖中的 LOCK_WAIT_TIME_ PERCENT 字段提供一個高層次的視圖,說明了在數據庫級別的鎖等待上花費的時間。為了獲得在鎖等待中花費了時間的工作負載的詳細視圖,請查詢 MON_GET_WORKLOAD 監(jiān)視器表函數。
清單 7. 在鎖等待中花費的時間
- db2 "SELECT varchar(workload_name,30) as workload_name,
- sum(lock_wait_time) as total_lock_wait_time,
- sum(lock_waits) as total_lock_waits,
- sum(lock_timeouts) as total_lock_timeouts,
- sum(lock_escals) as total_lock_escals
- FROM TABLE(MON_GET_WORKLOAD('',-2)) AS t
- GROUP BY workload_name
- ORDER BY total_lock_wait_time DESC"
#p#
步驟 7:調優(yōu)頁面清理活動
除了檢查系統資源瓶頸和鎖定問題,在所有數據庫環(huán)境中還有另一些重要的事項需要注意。頁面清理和預取是兩項重要活動,需要對它們進行適當調優(yōu)來獲得***性能。在某些情況下,如果頁面清理沒有得到正確的調優(yōu),則有可能出現 I/O 瓶頸。監(jiān)視表 MON_GET_BUFFERPOOL 提供了一些找出頁面清理和預取活動的指標。
清單 8. 頁面清理活動
- db2 "WITH BPMETRICS AS (
- SELECT bp_name,
- pool_data_writes, pool_async_data_writes,
- pool_index_writes, pool_async_index_writes,
- pool_no_victim_buffer, pool_lsn_gap_clns,
- pool_drty_pg_steal_clns, pool_drty_pg_thrsh_clns
- FROM TABLE(MON_GET_BUFFERPOOL('',-2)) AS METRICS)
- SELECT
- VARCHAR(bp_name,20) AS bp_name,
- pool_data_writes, pool_async_data_writes,
- CASE WHEN pool_data_writes > 0
- THEN DEC((FLOAT(pool_async_data_writes) / FLOAT(pool_data_writes)) * 100,5,2)
- ELSE NULL
- END AS PAGE_CLN_RATIO,
- pool_index_writes, pool_async_index_writes,
- CASE WHEN pool_index_writes > 0
- THEN DEC((FLOAT(pool_async_index_writes) / FLOAT(pool_index_writes)) * 100,5,2)
- ELSE NULL
- END AS IND_CLN_RATIO,
- pool_no_victim_buffer, pool_lsn_gap_clns,
- pool_drty_pg_steal_clns, pool_drty_pg_thrsh_clns
- FROM BPMETRICS"
以上查詢中的 Data 和 Index 頁面清理率應該接近 100%。如果該值小于 90%,那么頁面清洗的速度將無法跟上系統中臟頁的增長速度。
dirty_page_steal_clns 顯示了臟頁面竊取情況。理想情況下,該值必須為零。如果它超過邏輯讀取數量的一小部分,則需要清潔更多的頁面。請降低 CHG_PGS_THRESHOLD,并確保有足夠的 I/O 清潔器。
pool_no_victim_buffer 顯示了代理在可用頁面列表中無法找到可用頁面的次數。如果這個數字超過邏輯讀取幾個百分點,那么它就是有害的。請降低 CHG_PGS_THRESHOLD,并確保有足夠的 I/O 清潔器。
步驟 8:調優(yōu)預取活動
類似于頁面清理,我們還需要調優(yōu)預取活動。在一個真正的 OLTP 環(huán)境中,預取可能沒有用。但在 DSS 類的工作負載中,預取發(fā)揮著重要的作用。在理想的情況下,我們希望 IO_SERVERS IO_SERVERS(預取器)負責所有讀取,該操作實質上是異步進行的。下面的查詢顯示了由 IO_SERVERS 完成的 I/O 讀取百分比。
清單 9. 預取活動
- db2 "WITH BPMETRICS AS (
- SELECT bp_name,
- pool_data_p_reads, pool_async_data_reads,
- pool_temp_data_p_reads,
- pool_index_p_reads, pool_async_index_reads
- FROM TABLE(MON_GET_BUFFERPOOL('',-2)) AS METRICS)
- SELECT
- VARCHAR(bp_name,20) AS bp_name,
- pool_data_p_reads, pool_async_data_reads,
- CASE WHEN pool_data_p_reads > 0
- THEN DEC((FLOAT(pool_async_data_reads) / FLOAT(pool_data_p_reads +
- POOL_TEMP_DATA_P_READS)) * 100,5,2)
- ELSE NULL
- END AS PREFETCH_RATIO,
- pool_index_p_reads, pool_async_index_reads,
- CASE WHEN pool_index_p_reads > 0
- THEN DEC((FLOAT(pool_async_index_reads) / FLOAT(pool_index_p_reads)) * 100,5,2)
- ELSE NULL
- END AS PREFETCH_IDX_RATIO
- FROM BPMETRICS"
大于 90% 的值對于 PREFETCH_RATIO 而言是適合的值。
結束語
雖然這些步驟沒有涵蓋可能會出現的所有性能問題,但上面的方法主要側重于解決性能問題所使用的原則和策略。遵循這些步驟會幫助您縮小問題的范圍,并最終幫您解決問題。