程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> OLTP應用程序的DB2調優技巧

OLTP應用程序的DB2調優技巧

編輯:DB2教程

簡介

DB2 Universal Database®(UDB)是第一個支持多媒體和Web的關系數據庫管理系統,它的功能非常強大,足以滿足大公司的需求,並且它非常靈活,足以滿足中小企業的要求。DB2 產品系列軟件和因特網技術的結合使我們可以方便地跨不同平台訪問信息、使用信息並且保證信息安全。全世界有30 多萬家公司的6000 多萬個DB2 用戶依賴於 IBM 數據管理解決方案。

DB2 UDB 為大多數需要電子商務的應用程序(比如電子商務、企業資源計劃、客戶關系管理、供應鏈管理、Web自助服務和商業智能)提供支持。這是一種可伸縮的、工業級數據庫,非常適合用作電子商務發展過程中的數據管理基礎。

聯機事務處理(Online transaction processing,OLTP)是一類能為面向事務應用程序提供便利的應用程序,並可用來管理面向事務的應用程序,它通常用於處理許多行業的數據輸入和檢索事務,這些行業包括銀行、航空、郵購、超市和制造業。通常,OLTP 工作負載包括許多並發運行的短事務。如今的聯機事務處理日益要求支持跨網絡以及可能包括多家公司的事務。因此,新的 OLTP 軟件使用了客戶機/服務器處理和代理軟件,這種軟件允許事務在一個網絡的不同計算機平台上運行。

在任何一種數據庫系統中,性能是最重要的因素之一。本文根據由運行 OLTP 類型的性能基准測試程序(TPC-C、TPC-W、Trade2 等)所得到的經驗,著重討論了許多 DB2 性能調優技巧。雖然數據庫應用程序的性能會受許多因素影響,但是我們著重討論配置而不是諸如容量規劃、數據庫設計或應用程序設計之類的因素。

本文的組織結構如下:

有關性能的一些基本要素

更新目錄統計信息,這部分強調收集和維護最新數據庫統計信息的重要性,缺少這項工作常常是導致許多性能問題的源頭所在。

監控和調優數據庫配置參數,這部分按照重要性的順序描述了一列數據庫管理器參數和數據庫參數。通常,沒必要嘗試列表中的所有參數以實現性能目標。可以只嘗試其中位於列表頂部的那幾個,以查看是否有性能方面的改進。

有了這些技巧,就可以啟動自己的 OLTP 應用程序並使其擁有非常好的運行性能。

有關性能的一些基本要素

有足夠的內存。

對於 32 位系統,每個 CPU 至少使用 512 MB 的 RAM,最高可達每台機器 4 GB,以支持大量並發用戶所需的緩沖池、DB2 代理程序和其它共享內存對象。(請參閱 “緩沖池大小(BUFFPAGE)”一節以獲取有關緩沖池的更多信息。)可能需要更多的內存來支持在本地運行或作為存儲過程運行的應用程序。在 AIX® 上 JFS 文件高速緩存可以使用額外的內存來補充緩沖池。

對於 64 位系統,緩沖池實際上可以是任何大小。但是,對於使用大型數據庫的大多數電子商務 OLTP 應用程序,緩沖池大小實際上不需要超過 8 GB。越大當然越好,但是在某一點,當緩沖池命中率達到 98+% 時,會隨內存的增加命中率反而下降。並發用戶的數目(它影響 DB2 代理程序的數量)決定需要多少內存。

每個用戶連接至數據庫(即 DB2 代理程序)所需的內存數量取決於應用程序所執行的 SQL 語句的性質 - 比如打開的並發游標數以及所需的排序和臨時空間的數量。對於 OLTP 應用程序,所需的排序和臨時空間會比較少,一次只打開少數並發游標。

經驗:對於每個 DB2 代理程序,在 UNIX 中最少使用 1 MB 內存,在 Windows 中最少使用 500 KB 內存。如果使用了受防護的存儲過程,那麼除了運行存儲過程應用程序所需的內存之外,每個用戶連接還有兩個 DB2 代理程序。

有足夠的 I/O 處理能力。

必須有足夠的磁盤設備來確保充分的 I/O 並行性,以支持大容量的並發事務。對於中等工作負載而言,每個 CPU 至少應當有 5 到 10 個磁盤,對於高 I/O OLTP 工作負載而言,至少要有 20 個磁盤。操作系統(包括調頁空間)、DB2 日志和 DB2 表空間應當擁有各自的專用磁盤。應當有多個磁盤用於 DB2 日志、表和索引。

估計良好性能所需的 I/O 處理能力的正確方式,實際上是制作事務原型並找出每個事務需要多少 I/O,以及每秒需要處理多少事務。然後找出磁盤控制器和磁盤子系統的 I/O 速率以幫助確定需要多少控制器和磁盤。

有足夠的網絡帶寬。

必須有足夠大的網絡帶寬以支持工作負載。請確保網絡或任何中間集線器都不會成為瓶頸。當支持遠程訪問時這一點尤為重要。例如,T1 線路支持 1.544 Mb/s,這僅為 0.193 MB/s,而通常的 10 Mb/s 以太局域網可以支持 1.25 MB/s,吞吐量為 T1 線路的 6 倍。在 UNIX 上使用諸如 netstat 這樣的命令可以監控連接上的流量。

使用 DB2 控制中心(DB2 Control Center)的 DB2 性能配置向導(DB2 Performance Configuration Wizard)來設置初始的 DB2 數據庫管理器(Database Manager)和數據庫配置(Database Configuration)參數。

這個工具會詢問您一系列有關工作負載性質的問題,以便確定配置參數值的起始設置。您可以修改這些參數以滿足生產工作負載的需要。

適當地為表列建立索引。

確保查詢中進行連接操作的列都有索引。

如果為 ORDER BY 和 GROUP BY 所涉及的列建立了索引,那麼可以提高性能。

也可以將經常被訪問的數據作為 INCLUDE 子句中的列包含在索引中。

根據所使用的表和 SQL 語句,使用索引顧問程序(Index Advisor)(也稱為索引向導 (Index Wizard),可以從 DB2 控制中心調用該程序)來幫助確定使用一組合適的索引。

確保應用程序持有鎖的時間盡可能短。

當用戶操作涉及多個交互作用時,每個交互作用應當提交自己的事務並且應當在將活動返回給用戶之前釋放所有鎖。通過盡可能晚地啟動事務的第一個 SQL 語句(它啟動一個事務)並使事務的更新(插入、更新和刪除,這些操作要用到互斥鎖)盡可能接近提交階段,從而使事務的持續時間盡可能的短。

使用 DB2 注冊表參數 DB2_RR_TO_RS,通過不鎖定插入或更新行的下一個鍵,可以改進並發性。如果對同一組表進行操作的任何程序都沒有使用隔離級別 RR(可重復讀,Repeatable Read),那麼就可以使用上述操作。使用 DB2 快照(DB2 Snapshot)監控死鎖和鎖等待的數目。

使用存儲過程或復合 SQL 使網絡成本降到最低。

將用於 SQL 語句的網絡往返通信次數降至最低,可以減少網絡等待時間和上下文切換,這樣可以使應用程序持鎖的時間更短。通常,當 OLTP 事務有 4 個或 5 個以上語句時應當使用存儲過程。

另一方面,如果應用程序邏輯中涉及了某個復雜的 CPU 密集型處理,那麼將它放在運行於數據庫服務器上的存儲過程中會用光數據庫服務器上的額外 CPU 周期,從而犧牲一些數據庫操作。在這種情況下,要麼不使用存儲過程,要麼在客戶機端執行一部分邏輯,而在存儲過程中執行其余的邏輯。

有效地使用 SQL。

通常,如果一條 SQL 語句能完成任務,那麼就不使用多條 SQL 語句。當通過在查詢中設置更多謂詞來提供更詳細的搜索條件時,優化器就有機會作出更好的選擇。您還應該使查詢具有可選擇性,這樣數據庫就不會返回您不需要的行和列。例如,使用 SQL 來過濾您想要的行;不用返回所有行,然後要求應用程序執行過濾操作。

分析存取方案。

使用可視化說明(Visual Explain)或 db2exfmt 來分析每一條 SQL 語句。請確保使用合適的索引,從而在選擇和連接(join)表時,將必須在內部訪存的行數減到最少。

更新目錄統計信息

背景知識

RUNSTATS 實用程序用於更新系統目錄表中的統計信息,以幫助查詢優化過程。如果沒有這些統計信息,數據庫管理器可能會做出對 SQL 語句的性能產生不利影響的決定。RUNSTATS 實用程序允許您收集表和/或索引中所包含數據的統計信息。使用 RUNSTATS 實用程序收集基於表和索引數據的統計信息,以便為下列情形中的存取方案選擇過程提供精確的信息:

當向表裝入數據並創建了合適的索引時。

當用 REORG 實用程序重新組織表時。

當存在大量影響表及其索引的更新、刪除和插入操作時。(此處的“大量”可能意味著 10% 到 20% 的表和索引數據都受到了影響。)

在綁定性能至關重要的應用程序之前。

當您希望將新的和以前的統計信息進行比較時。定期進行統計使您能夠在早期階段發現性能問題。

當預取數量發生變化時。

當您已經使用了 REDISTRIBUTE NODEGROUP 實用程序時。

當對 SQL 查詢進行優化時,SQL 編譯器所做出的決定會受到優化器的數據庫內容模型的重大影響。優化器使用該數據模型來估計可以用於解決某個特定查詢的其它存取路徑的成本。數據模型中的關鍵元素是一組統計信息,該統計信息收集了有關數據庫中所包含的數據和系統目錄表中所存儲的數據的信息。這包括表、別名(nickname)、索引、列和用戶定義的函數(UDF)的統計信息。數據統計信息中的變化會引起對存取方案的選擇發生變化,該存取方案作為訪問所期望數據的最有效方法。

下面列舉了一些統計信息,這些統計信息可以幫助給優化器定義數據模型:

表中的頁數和非空的頁數。

從原始頁移到其它(溢出)頁的程度。

表中的行數。

有關單個列的統計信息,比如一列中唯一值的數量。

一個索引的群集程度;即,表中行的物理順序與索引的符合程度。

有關索引的統計信息,比如索引級別的數量和每個索引中葉子頁的數量。

經常使用的列值的出現次數。

列值在列中所有值中的分布狀況。

用戶定義的函數(UDF)的成本估計。

RUNSTATS 可以幫助您確定對數據庫的更改與性能之間的關系。統計信息顯示出表中的數據分布狀況。常規使用時,RUNSTATS 提供了在一段時期內有關表和索引的數據,從而隨著時間的流逝,可以確定數據模型的性能趨勢。在使用 RUNSTATS 之後需要重新綁定使用靜態 SQL 的應用程序,這樣查詢優化器就可以選擇新統計信息所給出的最佳存取方案。但是,對於使用動態 SQL 的應用程序(比如大多數供應商應用程序)而言,沒必要進行重新綁定,因為語句的優化是根據統計信息在運行時進行的。當有關表的統計信息不准確時,可能會造成性能問題。最糟的情況是,某個特定的 SQL 語句可能會造成 DB2 使用表掃描而不是使用索引掃描。

如何更新統計信息

只有當進行顯式的請求時,對象的統計信息才會在系統目錄表中被更新。有幾種方法可以更新部分或全部統計信息:

使用 RUNSTATS(運行統計信息,run statistics)實用程序。

使用帶有指定的統計信息收集選項的 LOAD。

對針對一組預先定義的目錄視圖進行操作的 SQL UPDATE 語句進行編碼。

使用“reorgchk update statistics”命令。

當您不完全知道所有表名或表名實在太多時,進行 RUNSTATS 的最簡單方法就是使用“db2 reorgchk update statistics”命令。正確的腳本如下:

db2 -v connect to DB_NAME
db2 -v "select tbname, nleaf, nlevels, stats_time from sysibm.sysindexes"
db2 -v reorgchk update statistics on table all
db2 -v "select tbname, nleaf, nlevels, stats_time from sysibm.sysindexes"
db2 -v terminate

我們上面所選的示例不需要表名。這一命令對所有表執行 RUNSTATS。

記住: 在填充數據庫之後再運行 RUNSTATS 實用程序。

如果您知道表名並且想避免對大量表運行 RUNSTATS 實用程序(因為這樣做可能要花很長時間),那麼一次對一張表進行 RUNSTATS 更為可取。命令如下:

db2 -v runstats on table
TAB_NAME and indexes all

這個命令將收集該表及其所有索引(基本級別)的統計信息。

查看是否運行了 RUNSTATS

要查看是否對數據庫執行了 RUNSTATS,一種快捷方法便是查詢一些系統目錄表。例如,如上面的腳本所示,可以運行下面這條命令:

db2 -v "select tbname, nleaf, nlevels, stats_time from sysibm.sysindexes"

如果還未運行 RUNSTATS,您會看到 nleaf 和 nlevels 列為“-1”且 stats_time 列為“-”。如果已經運行了 RUNSTATS,則這些列包含實際的數字,並且如果運行過 RUNSTATS,則 stats_time 列將包含時間戳記。如果您認為 stats_time 中所示時間離現在已有很長一段時間,那就該再次運行 RUNSTATS。

監控和調優數據庫配置參數

下面這些有關數據庫配置調優的技巧將使您在 OLTP 環境中取得非常好的性能,同時使您能夠避免顯而易見的“陷阱”。在配置參數中,數據庫管理器配置參數需要重新啟動數據庫管理器,而為了使更改生效,大多數數據庫配置參數都要求應用程序重新連接到數據庫。

這裡描述的配置參數包括:

緩沖池大小

日志緩沖區大小

應用程序堆大小

排序堆大小和排序堆阈值

代理程序的數目

活動應用程序的最大數目

異步頁清除程序的數目

I/O 服務器的數目

編入組中的提交數目

緩沖池大小

背景知識

緩沖池是內存中的一塊存儲區域,用於臨時讀入和更改數據庫頁(包含表行或索引項)。緩沖池的用途是為了提高數據庫系統的性能。從內存訪問數據要比從磁盤訪問數據快得多。因此,數據庫管理器需要從磁盤讀取或寫入磁盤的次數越少,性能就越好。對一個或多個緩沖池進行配置之所以是調優的最重要方面,是因為連接至數據庫的應用程序的大多數數據(不包括大對象和長字段數據)操作都在緩沖池中進行。

缺省情況下,應用程序使用緩沖池 IBMDEFAULTBP,它是在創建數據庫時創建的。當 SYSCAT.BUFFERPOOLS 目錄表中該緩沖池的 NPAGES 值為 -1 時,DB2 數據庫配置參數 BUFFPAGE 控制著緩沖池的大小。否則會忽略 BUFFPAGE 參數,並且用 NPAGES 參數所指定的頁數創建緩沖池。

建議

對於僅使用一個緩沖池的應用程序,將 NPAGES 更改成 -1,這樣 BUFFPAGE 就可以控制該緩沖池的大小。這使得更新和報告緩沖池大小以及其它 DB2 數據庫配置參數變得更加方便。

確保可以使用數據庫配置中的 BUFFPAGE 參數來控制緩沖池大小之後,將該參數設置成合適的值。根據數據庫的大小和應用程序的性質將該參數設置成一個合理的大值,這種做法很安全。通常,該參數的缺省值非常小,可能滿足不了要求。請考慮下列情況:

一開始,如果您的機器上有足夠大的內存,請將 BUFFPAGE 設置成 40000 個頁(160 MB),或者等於機器總內存的 10%。

對於大型 OLTP 數據庫,在保持系統穩定的同時為緩沖池留出盡可能多的內存。一開始,先嘗試使用 1.6 GB 的內存,然後嘗試用更多內存。

如何更改該參數

運行下面這個腳本,以便:

驗證目錄值

啟用數據庫配置參數 BUFFPAGE

更新所有數據庫的 BUFFPAGE 值。

db2 -v connect to DB_NAME
db2 -v select * from syscat.bufferpools
db2 -v alter bufferpool IBMDEFAULTBP size -1
db2 -v connect reset
db2 -v update db cfg for dbname using BUFFPAGE bigger_value
db2 -v terminate

研究步驟

要確定數據庫的緩沖池大小是否由 BUFFPAGE 參數所決定,請運行:

db2 -v connect to DB_NAME
db2 -v SELECT * from SYSCAT.BUFFERPOOLS
db2 -v connect reset
db2 -v terminate

檢查結果。如果每個緩沖池都有一個為“-1”的 NPAGES 值,那麼緩沖池大小是由數據庫配置中的 BUFFPAGE 參數控制的。

要確定緩沖池大小是否足夠大,請在運行應用程序時收集數據庫和/或緩沖池的快照。類似於下面的腳本為您提供這些所需的信息:

db2 -v update monitor switches using bufferpool on
db2 -v get monitor switches
db2 -v reset monitor all

-- run your application --
db2 -v get snapshot for all databases > snap.out
db2 -v get snapshot for dbm >> snap.out
db2 -v get snapshot for all bufferpools >> snap.out
db2 -v reset monitor all
db2 -v terminate

請確保您在斷開數據庫連接之前發出“db2 -v get snapshot”。當最後一個應用程序與數據庫斷開連接時,該數據庫停止運行,同時所有快照統計信息將會丟失。要確保一直存在使數據庫處於正常運行狀態的連接,請使用下列方法之一:

在收集快照的窗口中保持一個單獨的連接。

使用 DB2 ACTIVATE DATABASE 命令。

在數據庫快照或緩沖池快照的快照輸出中,查找下列“logical reads”和“physical reads”,這樣就可以計算出緩沖池命中率,它可以幫助您調優緩沖池:

-- Related lines from a sample of bufferpool snapshots --
Buffer pool data logical reads = 702033
Buffer pool data physical reads = 0
Buffer pool data writes = 414
Buffer pool index logical reads = 168255
Buffer pool index physical reads = 0

緩沖池命中率表明數據庫管理器不需要從磁盤裝入頁(即該頁已經在緩沖池中)就能處理頁請求的時間百分比。緩沖池的命中率越高,使用磁盤 I/O 的頻率就越低。按如下計算緩沖池命中率:

(1 - ((buffer pool data physical reads + buffer pool index physical reads) /
(buffer pool data logical reads + pool index logical reads))
) * 100%

這個計算考慮了緩沖池高速緩存的所有頁(索引和數據)。理想情況下,該比率應當超過 95%,並盡可能接近 100%。要提高緩沖池命中率,請嘗試下面這些方法:

增加緩沖池大小。

考慮分配多個緩沖池,如果可能的話,為每個經常被訪問的大表所屬的表空間分配一個緩沖池,為一組小表分配一個緩沖池,然後嘗試一下使用不同大小的緩沖池以查看哪種組合會提供最佳性能。

如果已分配的內存不能幫助提高性能,那麼請避免給緩沖池分配過多的內存。應當根據取自測試環境的快照信息來決定緩沖池的大小。

日志緩沖區大小(LOGBUFSZ)

背景知識

LOGBUFSZ 是一個數據庫配置參數。它是用於日志緩沖區的參數。它允許您指定數據庫共享內存的大小以用作在將日志記錄寫到磁盤之前這些記錄的緩沖區。當下列事件之一發生時會將日志記錄寫到磁盤:

事務提交。

日志緩沖區已滿。

其它某個內部數據庫管理器事件發生時。

將日志記錄存在緩沖區將產生更加有效的日志文件 I/O,這是因為這樣一來可以降低將日志記錄寫到磁盤的頻率,同時每次可寫更多的日志記錄。如果對專用的日志磁盤有相當多的讀操作,或者希望有較高的磁盤利用率,那麼可以增加這個緩沖區的大小。當增加這個參數的值時,也要考慮 DBHEAP 參數,因為日志緩沖區使用的空間由 DBHEAP 參數所控制。

如何更改該參數

我們發現該參數的缺省值為 8(4KB 頁),這對於 OLTP 數據庫而言通常不夠大。LOGBUFSZ 的最佳值為 128 個或 256 個 4KB 頁。例如,可以使用下面這個命令來更改該參數值:

db2 -v update database cfg for DB_NAME using LOGBUFSZ 256
db2 -v terminate

研究步驟

通過查看下面這個示例中所示各行,使用數據庫快照來確定 LOGBUFSZ 參數的值是否為最佳值:

Log pages read = 0
Log pages written = 12644

一般而言,“log pages read”和“log pages written”之比應當盡可能小。理想情況下,“log pages read”的值應為 0,而“log pages written”的值應很大。當 log pages read 太多時,意味著需要一個較大的 LOGBUFSZ。

應用程序堆大小(APPHEAPSZ)

背景知識

APPHEAPSZ 是一個數據庫配置參數,它定義了代表某個特定代理程序或子代理程序的數據庫管理器可以使用的私有內存頁數。在為應用程序初始化代理程序或子代理程序時分配堆。分配的堆大小是處理給予代理程序或子代理程序的請求所需的最小值。當代理程序或子代理程序需要更多的堆空間以處理較大的 SQL 語句時,數據庫管理器將按照需要分配內存,所分配的內存大小最大可達到該參數所指定的最大值。

如何更改該參數

下面這條命令可以將缺省值(DB2 EE 為 128 個 4KB 頁,DB2 EEE 為 64 個 4KB 頁)更改成最佳值:

db2 -v update db cfg for DB_NAME using applheapsz 256
db2 -v terminate

研究步驟

當應用程序接收到一個表明應用程序堆中存儲空間不夠的錯誤時,應該增加 APPHEAPSZ 的值。

排序堆大小(SORTHEAP)和排序堆阈值(SHEAPTHRES)

背景知識

SORTHEAP 是一個數據庫配置參數,它定義了私有排序所使用的私有內存頁的最大數目,或共享排序所使用的共享內存頁的最大數目。如果排序是私有排序,那麼該參數影響代理程序私有內存。如果排序是共享排序,那麼該參數影響數據庫的共享內存。每個排序都有單獨的由數據庫管理器按需分配的排序堆。在排序堆中對數據進行排序。如果由優化器來指導排序堆大小的分配,那麼用優化器提供的信息來分配的排序堆的大小要小於由該參數所指定的排序堆大小。

SHEAPTHRES 是一個數據庫管理器配置參數。私有和共享排序所使用內存的來源不一樣。共享排序內存區的大小是在第一次連接到數據庫時根據 SHEAPTHRES 值以靜態方式預先確定的。私有排序內存區的大小是不受限制的。對於私有排序和共享排序,應用 SHEAPTHRES 參數的方式不同:

對於私有排序,SHEAPTHRES 是對私有排序在任何給定的時間可以消耗的全部內存的實例級“軟”限制。當實例的總私有排序內存消耗量達到這一限制時,為其它進入的私有排序請求而分配的內存會大大減少。

對於共享排序,SHEAPTHRES 是對共享排序在任何給定的時間可以消耗的全部內存的數據庫級“硬”限制。當達到這一限制時,不允許有其它共享排序內存請求,直到總的共享內存消耗量回落到 SHEAPTHRES 所指定的限制以下。

使用排序堆的操作示例包括內存中表的散列連接和操作。阈值的顯式定義防止數據庫管理器將過多數量的內存用於大量排序。

建議

使用數據庫系統監視器來跟蹤排序活動。

使用合適的索引使排序堆的使用降到最低。

當需要頻繁進行大型排序時,增加 SORTHEAP 的值。

如果增加 SORTHEAP,請確定是否還需要調整數據庫管理器配置文件中的 SHEAPTHRES 參數。

優化器用排序堆大小來確定存取路徑。在更改該參數後請考慮重新綁定應用程序(使用 REBIND PACKAGE 命令)。

理想情況下,應當將排序堆阈值(SHEAPTHRES)參數合理地設置為在數據庫管理器實例中設置的 SORTHEAP 參數最大值的倍數。該參數至少應當是實例中任何數據庫所定義的最大 SORTHEAP 的兩倍。

如何更改這些參數

要更改 SORTHEAP 和 SHEAPTHRES 的值,請運行以下命令: -- SORTHEAP should be changed for individual database --
db2 -v update db cfg for DB_NAME using SORTHEAP a_value
-- SHEAPTHRES is a database manager parameter --
db2 -v update dbm cfg using SHEAPTHRES b_value
db2 -v terminate

研究步驟

OLTP 應用程序不應該執行大型排序。大型排序在 CPU 和 I/O 資源方面的成本太高了。通常,SORTHEAP 大小的缺省值(256 個 4KB 頁)就足夠了。事實上,對於高並發性 OLTP,您可能希望降低這個缺省值。當需要進一步研究時,可以發出下面這條命令:

db2 -v update monitor switches using sort on

然後,讓您的應用程序運行一會,然後輸入:

db2 -v get snapshot for database on DBNAME

看一下下面這個示例中的輸出:

Total sort heap allocated = 0
Total sorts = 1
Total sort time (ms) = 0
Sort overflows = 0
Active sorts = 0
Commit statements attempted = 1
Rollback statements attempted = 0
Dynamic statements attempted = 4
Static statements attempted = 1
Binds/precompiles attempted = 0

根據該輸出,可以計算每個事務的排序數目,並可以計算溢出了可用於排序的內存的那部分排序的百分比。 SortsPerTransaction
= (Total Sorts) / (Commit statements attempted + Rollback statements attempted)
PercentSortOverflow
= (Sort overflows * 100 ) / (Total sorts)

經驗:如果 SortsPerTransaction 大於 5,它可能表明每個事務的排序太多。如果 PercentSortOverflow 大於 3%,那麼可能發生了嚴重的、未曾預料到的大型排序。發生這種情況時,增加 SORTHEAP 只會隱藏性能問題 - 卻無法修正它。這個問題的正確解決方案是通過添加正確的索引改進有問題的 SQL 語句的存取方案。

代理程序的數目(MAXAGENTS、NUM_POOLAGENTS 和 NUM_INITAGENTS)

背景知識

這些是數據庫管理器配置參數。

MAXAGENTS 參數表明在任何給定時間接受應用程序請求的數據庫管理器代理程序的最大數目。MAXAGENTS 的值應當至少是每個被並發地訪問的數據庫中的 MAXAPPLS(並發應用程序最大數目)值的總和。如果數據庫的數量大於 NUMDB 參數,那麼最安全的方案就是使用 NUMDB 和 MAXAPPLS 最大值的乘積。每個額外的代理程序都需要一些資源開銷,這些開銷在啟動數據庫管理器時會分配給代理程序。

NUM_POOLAGENTS 參數是用於評定您希望代理程序池增加到多大的准則。如果所創建的代理程序多於該參數值所指明的數目,那麼當代理程序執行完自己當前的請求後將終止運行而不是返回給代理程序池。如果該參數的值為 0,將按照需要創建代理程序,在代理程序執行完自己當前的請求後終止運行。

要避免因在並發連接許多應用程序的 OLTP 環境中頻繁創建和終止代理程序而產生的成本,請將 NUM_POOLAGENTS 的值增加到接近 MAXAGENTS 值。

NUM_INITAGENTS 參數決定空閒代理程序的初始數量,這些代理程序是在 DB2START 時在代理程序池中創建的。指定初始代理程序數目要合適(盡管並非必要條件),這可以縮短“熱身”時間。

建議

在大多數情況下,將 MAXAGENTS 和 NUM_POOLAGENTS 的值設置成略微大於並發應用程序連接的最大預計數目。

讓 NUM_INITAGENTS 保留為缺省值會比較好。

如何更改該參數

為了更改這些參數,請運行以下命令: db2 -v update dbm cfg using MAXAGENTS a_value
db2 -v update dbm cfg using NUM_POOLAGENTS b_value
db2 -v update dbm cfg using NUM_INITAGENTS c_value
db2 -v terminate

研究步驟

在運行期間的任何時候,您都可以使用下面這個命令來獲取數據庫管理器的快照數據: db2 -v get snapshot for database manager

看一下下列輸出行: High water mark for agents registered = 4
High water mark for agents waiting for a token = 0
Agents registered = 4
Agents waiting for a token = 0
Idle agents = 0
Agents assigned from pool = 5
Agents created from empty pool = 4
Agents stolen from another application = 0
High water mark for coordinating agents = 4
Max agents overflow = 0

如果您發現“Agents waiting for a token”或“Agents stolen from another application”不等於 0,則可能需要增加 MAXAGENTS 以允許數據庫管理器可以使用更多的代理程序。

鎖(LOCKLIST、MAXLOCKS 和 LOCKTIMEOUT)

背景知識

這些與鎖相關的控制都是數據庫配置參數:

LOCKLIST 表明分配給鎖列表的存儲容量。每個數據庫都有一個鎖列表,鎖列表包含了並發連接到該數據庫的所有應用程序所持有的鎖。鎖定是數據庫管理器用來控制多個應用程序並發訪問數據庫中數據的機制。行和表都可以被鎖定。根據對象是否還持有其它鎖,每把鎖需要 32 個或 64 個字節的鎖列表:

需要 64 個字節來持有某個對象上的鎖,在這個對象上,沒有持有其它鎖。

需要 32 個字節來記錄某個對象上的鎖,在這個對象上,已經持有一個鎖。

MAXLOCKS 定義了應用程序持有的鎖列表的百分比,在數據庫管理器執行鎖升級之前必須填充該鎖列表。當一個應用程序所使用的鎖列表百分比達到 MAXLOCKS 時,數據庫管理器會升級這些鎖,這意味著用表鎖代替行鎖,從而減少列表中鎖的數量。當任何一個應用程序所持有的鎖數量達到整個鎖列表大小的這個百分比時,對該應用程序所持有的鎖進行鎖升級。如果鎖列表用完了空間,那麼也會發生鎖升級。數據庫管理器通過查看應用程序的鎖列表並查找行鎖最多的表,來決定對哪些鎖進行升級。如果用一個表鎖替換這些行鎖,將不再會超出 MAXLOCKS 值,那麼鎖升級就會停止。否則,鎖升級就會一直進行,直到所持有的鎖列表百分比低於 MAXLOCKS。MAXLOCKS 參數乘以 MAXAPPLS 參數不能小於 100。

雖然升級過程本身並不用花很多時間,但是鎖定整個表(相對於鎖定個別行)降低了並發性,而且數據庫的整體性能可能會由於對受鎖升級影響的表的後續訪問而降低。

下面是一些控制鎖列表大小的建議:

經常進行提交以釋放鎖。

當執行大量更新時,更新之前,在整個事務期間鎖定整個表(使用 SQL LOCK TABLE 語句)。這只使用了一把鎖從而防止其它事務妨礙這些更新,但是對於其他用戶它的確減少了數據並發性。

使用 altER TABLE 語句的 LOCKSIZE 參數控制如何在持久基礎上對某個特定表進行鎖定。

查看應用程序使用的隔離級別。使用可重復讀隔離級別在某些情況下可能會導致自動執行表鎖定。當有可能減少所持有共享鎖的數量時,可以使用游標穩定性(Cursor Stability)隔離級別。如果沒有損害應用程序完整性需求,那麼可以使用未提交的讀隔離級別而不是游標穩定性隔離級別,以進一步減少鎖的數量。

使用下列步驟確定鎖列表所需的頁數:

計算鎖列表大小的下限:(512 * 32 * MAXAPPLS) / 4096,其中 512 是每個應用程序平均所含鎖數量的估計值,32 是對象(已有一把鎖)上每把鎖所需的字節數。

計算鎖列表大小的上限:(512 * 64 * MAXAPPLS) / 4096,其中 64 是某個對象上第一把鎖所需的字節數。

對於您的數據,估計可能具有的並發數,並根據您的預計為鎖列表選擇一個初始值,該值位於您計算出的上限和下限之間。

使用數據庫系統監視器調優 MAXLOCKS 值。

設置 MAXLOCKS 時,請考慮鎖列表的大小(LOCKLIST):

MAXLOCKS = 100 * (512 鎖/應用程序 * 32 字節/鎖 * 2) / (LOCKLIST * 4096 字節)

該樣本公式允許任何應用程序持有的鎖是平均數的兩倍。如果只有幾個應用程序並發地運行,則可以增大 MAXLOCKS,因為在這些條件下鎖列表空間中不會有太多爭用。

LOCKTIMEOUT 指定了應用程序為獲取鎖所等待的秒數。這有助於應用程序避免全局死鎖。

如果將該參數設置成 0,那麼應用程序將不等待獲取鎖。在這種情形中,如果請求時沒有可用的鎖,那麼應用程序立刻會接收到 -911。

如果將該參數設置成 -1,那麼將關閉鎖超時檢測。在這種情形中,應用程序將等待獲取鎖(如果請求時沒有可用的鎖),一直到被授予了鎖或出現死鎖為止。

建議

設置 LOCKTIMEOUT 以快速檢測由於異常情形而出現的等待,比如事務被延遲了(可能是由於用戶離開了他們的工作站)。將它設置得足夠高,這樣有效的鎖請求就不會因為高峰時的工作負載而超時,在高峰時等待獲取鎖的時間將延長。

在聯機事務處理(OLTP)環境中,這個值從 30 秒開始。在只進行查詢的環境中可以從一個更大的值開始。無論哪種情況,都可使用基准測試技術來調優該參數。

如何更改這些參數

要更改鎖參數,請運行以下命令: db2 -v update db cfg for DB_NAME using LOCKLIST a_number
db2 -v update db cfg for DB_NAME using MAXLOCKS b_number
db2 -v update db cfg for DB_NAME using LOCKTIMEOUT c_number
db2 -v terminate

研究步驟

一旦鎖列表滿了,由於鎖升級生成更多的表鎖和更少的行鎖,因此減少了數據庫中共享對象的並發性,從而降低了性能。另外,應用程序間可能會發生更多死鎖(因為它們都等待數量有限的表鎖),這會導致事務被回滾。當數據庫的鎖請求達到最大值時,應用程序將接收到值為 -912 的 SQLCODE。如果鎖升級造成性能方面的問題,則可能需要增大 LOCKLIST 參數或 MAXLOCKS 參數的值。可以使用數據庫系統監視器來確定是否發生鎖升級,跟蹤應用程序(連接)遭遇鎖超時的次數,或者數據庫檢測到的所有已連接應用程序的超時情形。

首先,運行下面這個命令以打開針對鎖的 DB2 監視器: db2 -v update monitor switches using lock on
db2 -v terminate

然後收集數據庫快照: db2 -v get snapshot for database on DB_NAME

在快照輸出中,檢查下列各項: Locks held currently = 0
Lock waits = 0
Time database waited on locks (ms) = 0
Lock list memory in use (Bytes) = 504
Deadlocks detected = 0
Lock escalations = 0
Exclusive lock escalations = 0
Agents currently waiting on locks = 0
Lock Timeouts = 0
Internal rollbacks due to deadlock = 0

如果“Lock list memory in use (Bytes)”超過定義的 LOCKLIST 大小的 50%,那麼就增加 LOCKLIST 數據庫配置參數中的 4KB 頁的數量。鎖升級、鎖超時和死鎖將表明系統或應用程序中存在某些潛在問題。鎖定問題通常表明應用程序中存在一些相當嚴重的並發性問題,在增大鎖列表參數的值之前應當解決這些問題。

活動應用程序的最大數目(MAXAPPLS)

背景知識

MAXAPPLS 是一個數據庫配置參數。它指定了可以連接到數據庫的並發應用程序(本地和遠程)的最大數量。由於需要給連接到數據庫的每個應用程序分配一些私有內存,因此允許有更多並發應用程序將意味著用去更多內存。該參數值必須大於等於已連接應用程序的數量,加上這些相同的應用程序中完成兩階段提交或回滾過程中可能並發存在的數量的總和。

建議

要運行 OLTP 應用程序,請確保將 MAXAPPLS 的值設置正確(足夠大但不能是沒必要的大)以容納最多的並發用戶/連接。對於那些使用連接池的應用程序,我們建議將 MAXAPPLS 的值設置成比連接池的大小大 1 或 2(這樣做只是為了以防需要調用命令行連接來同時做一些事情)。

如何更改該參數

要更改 MAXAPPLS 的值,請運行下面的命令: db2 -v update db cfg for DB_NAME using MAXAPPLS a_number
db2 -v terminate

研究步驟

當應用程序嘗試連接數據庫,但是連接到數據庫的應用程序數已經達到了 MAXAPPLS 的值時,會向應用程序返回下面這個錯誤,表明連接到該數據庫的應用程序數已達到了最大值。

SQL1040N The maximum number of applications is already connected to the
database. SQLSTATE=57030

異步頁清除程序的數目(NUM_IOCLEANERS)

背景知識

NUM_IOCLEANERS 是一個數據庫配置參數,它可以讓您指定數據庫的異步頁清除程序的數目。在數據庫代理程序需要緩沖池中的空間之前,這些頁清除程序將緩沖池中已更改的頁寫到磁盤。這允許代理程序不必等待已更改頁被寫到磁盤就可以讀取新頁。因此,這會加快應用程序事務的運行。

如果將該參數設置成 0,則不啟動頁清除程序,結果,數據庫代理程序將緩沖池中的所有頁寫到磁盤。該參數會對存儲在多個物理存儲設備上的單個數據庫的性能產生顯著影響,這是因為在這種情況下其中某個設備極有可能處於空閒狀態。如果沒有配置頁清除程序,則應用程序可能會遇到不時發生的“日志已滿”情況。

如果連接到數據庫的應用程序主要執行更新數據的事務,那麼增加清除程序的數目會提高性能。增加頁清除程序的數量還會減少“軟”故障(比如斷電)的恢復時間,因為磁盤上數據庫的內容在任何給定時候都是比較新的。

當設置該參數的值時要考慮下面這些因素:

如果有多個事務針對數據庫運行,則將該參數的值設置在 1 到該數據庫所使用的物理存儲器的數量之間。有一個建議:至少將該參數的值設置成您系統上 CPU 的數量。

在具有高更新事務率的環境下,可能需要配置較多的頁清除程序。

在具有大緩沖池的環境下,也可能需要配置較多的頁清除程序。

如何更改該參數

可以用下面的命令來為該參數設置一個新值: db2 -v update db cfg for DB_NAME using NUM_IOCLEANERS a_number
db2 -v terminate

研究步驟

使用數據庫系統監視器,利用有關從緩沖池進行寫操作的快照數據(或事件監視器)信息來幫助您調優該配置參數。

當使用快照和收集緩沖池的快照數據時,監控下列計數器:

Buffer pool data writes = 0
Asynchronous pool data page writes = 0
Buffer pool index writes = 0
Asynchronous pool index page writes = 0
LSN Gap cleaner triggers   = 0
Dirty page steal cleaner triggers = 0
Dirty page threshold cleaner triggers = 0

如何決定該減少還是該增加 NUM_IOCLEANERS?

如果下面這兩個條件成立,則 減少NUM_IOCLEANERS:

“Buffer pool data writes”約等於“Asynchronous pool data page writes”。

“Buffer pool index writes”約等於“Asynchronous pool index page writes”。

只要下面這兩個條件有一個成立,則 增加NUM_IOCLEANERS:

“Buffer pool data writes”遠遠大於“Asynchronous pool data page writes”。

“Buffer pool index writes”遠遠大於“Asynchronous pool index page writes”。

Dirty page steal cleaner triggers 指出調用頁清除程序的次數,因為在數據庫“受損”緩沖區替換期間需要同步寫操作。為了有更好的響應時間,該數值應當盡可能低。利用上面所示的計數器,可以使用下面的公式計算用該元素表示的所有清除程序調用的百分比: Dirty page steal cleaner triggers / (Dirty page steal cleaner triggers +
Dirty page threshold cleaner triggers +
LSN Gap cleaner triggers)

如果該比率很高,則它可能表明您所定義的頁清除程序太少了。頁清除程序太少會使故障恢復時間變長。

I/O 服務器的數目(NUM_iOSERVERS)

背景知識

諸如備份和恢復之類的實用程序使用 I/O 服務器代表數據庫代理程序執行預取 I/O 和異步 I/O。該參數是一個數據庫配置參數,用於指定數據庫的 I/O 服務器的數目。超過這個數量的預取和實用程序 I/O 在任何時候都不能在數據庫中運行。在啟動 I/O 操作時,I/O 服務器處於等待狀態。由於從數據庫代理程序直接調度非預取 I/O,因此非預取 I/O 不受 NUM_iOSERVERS 約束。

建議

在 OLTP 環境中,請使用缺省值。

如何更改該參數

使用下面的命令為 NUM_iOSERVERS 設置新值: db2 -v update db cfg for DB_NAME using NUM_iOSERVERS a_number
db2 -v terminate

編入組中的提交數目(MINCOMMIT)

背景知識

MINCOMMIT 是數據庫配置參數,它讓您把將日志記錄寫到磁盤的工作一直延遲到執行了最小數量的提交為止。該延遲可以有助於減少與寫日志記錄相關的數據庫管理器開銷。這意味著當您針對數據庫運行多個應用程序並且在非常短的時間范圍內應用程序請求大量提交時可以提高性能。只有當該參數值大於 1 並且當連接到數據庫的應用程序數量大於或等於該參數值時,才會發生這個提交分組。當執行提交分組時,應用程序提交請求會被掛起,直到時間過去 1 秒或提交請求的數量等於該參數值。

建議

MINCOMMIT 的缺省值為 1。如果多個讀/寫應用程序通常請求並發數據庫提交,則從缺省值開始遞增該參數值。這將產生更有效率的日志文件 I/O,因為使用日志文件 I/O 的次數比較少,而每次使用日志文件 I/O 時所寫的日志記錄比較多。如果您認為缺省值不夠大,那麼建議您從 3 開始進行調整,在 3 的附近嘗試以查看性能對工作負載的影響。您還可以對每秒鐘的事務量進行采樣,並調整該參數以適應每秒鐘的峰值事務量(或者采用它的某個較大的百分比)。適應峰值活動使得在重負載期間寫日志記錄的開銷減到了最低。

如果增大 MINCOMMIT,可能還需要增大 LOGBUFSZ 參數以避免在這些重負載期間強制將已滿的日志緩沖區寫入磁盤。在這種情況下,LOGBUFSZ 應該等於: MINCOMMIT * (log space used, on average, by a transaction)

下面介紹了如何使用數據庫系統監視器幫助您調優該參數的一些方法:

計算每秒鐘的峰值事務數:

通過采用典型一天中的監視器樣本,可以確定重負載時期。它的一種實現方法是:

1. 在測量開始時,發出下面這個命令: db2 -v reset monitor for database db_name

(這不會使高水位的計數器復位。)

2. 在測量完畢後,發出下面這個命令: db2 -v get snapshot for database on db_name

3. 使用以下輸出來計算事務的峰值: Last reset timestamp = 06-12-2001 14:51:43.786876
Snapshot timestamp = 06-12-2001 14:56:27.787088
Commit statements attempted = 1011
Rollback statements attempted = 10
Log space used by the database (Bytes) = 3990

讓 totalTransactions等於“commit statements attempted”和“rollback statements attempted”的總和。

讓 totalElapsedTime(單位為秒)等於“Last reset timestamp”和“Snapshot timestamp”的差。如下計算每秒事務數: NumOfTransPerSecond = totalTransactions / totalElapsedTime

計算每個事務所使用的日志空間:

用類似的方式,通過在一段時間內對一些事務使用抽樣技術,可以通過下面這個監視器元素: log_space_used(所使用的工作日志空間單元)計算出使用的日志空間的平均值。

1. 在測量開始時使用下面這個命令將感興趣的數據庫的監視器復位: db2 -v reset monitor for database db_name.

2. 在測量完畢後使用下面這個命令獲取快照: db2 -v get snapshot for database on db2_name.

3. 產生如上所示的輸出。

4. 可以使用下面這個公式計算出每個事務所使用的日志空間: LogSpaceUsedPerTrans = log_space_used / totalTransactions

如何更改該參數

使用下面的命令更改 MINCOMMIT 值: db2 -v update db cfg for
DB_NAME using MINCOMMIT
a_number
db2 -v terminate

結束語

本文描述了一些 DB2 性能方面的基本要素、調優技巧和技術以及可能影響 OLTP 性能的一些主要的 DB2 配置參數。通過按照這裡所描述的一些簡單步驟,可以設置、監控和調優 DB2 數據庫系統。我們希望本文所提供的指導能幫助您實現最優化 DB2 應用程序性能的目標。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved