為了盡可能好地進行頁清除:
* 將 CHNGPGS_THRESH 數據庫配置參數的值從缺省的 60 減少到 5 這么低。這個參數決定緩沖池中臟頁的閾值百分比,當臟頁達到這個百分比時,就會啟動頁清除。
* 嘗試啟用注冊表變量 DB2_USE_ALTERNATE_PAGE_CLEANING(在 DB2 V8 FixPak 4 中最新提供)。通過將這個變量設置成 ON,可以為頁清除提供一種比缺省方法(基于 CHNGPGS_THRESH 和 LSN 間隙觸發器)更積極的方法。我沒有評測過其效果。請參閱 FixPak 4 Release Notes 以了解這方面的信息。
* 確保 NUM_IOCLEANERS 數據庫配置參數的值至少等于數據庫中物理存儲設備的數量。
至于 I/O 本身,當需要建立索引時,可以通過使用盡可能大的緩沖池來將 I/O 活動減至最少。如果不存在索引,則使用較大的緩沖池幫助不大,而只是推遲了 I/O。也就是說,它允許所有新頁暫時安放在緩沖池中,但是最終仍需要將這些頁寫到磁盤上。
當發生將頁寫到磁盤的 I/O 時,通過一些常規的 I/O 調優步驟可以加快這一過程,例如:
* 將表空間分布在多個容器(這些容器映射到不同磁盤)。
* 盡可能使用最快的硬件和存儲管理配置,這包括磁盤和通道速度、寫緩存以及并行寫等因素。
* 避免 RAID5(除非是與像 Shark 這樣有效的存儲設備一起使用)。
5. 鎖
缺省情況下,每一個插入的行之上都有一個 X 鎖,這個鎖是在該行創建時就開始有的,一直到 insert 被提交。有兩個跟 insert 和鎖相關的性能問題:
* 為獲得和釋放鎖而產生的 CPU 開銷。
* 可能由于鎖沖突而導致的并發問題。
對于經過良好優化的批量插入,由獲得每一行之上的一個 X 鎖以及后來釋放該鎖引起的 CPU 開銷是比較可觀的。對于每個新行之上的鎖,惟一可以替代的是表鎖(DB2 中沒有頁鎖)。當使用表鎖時,耗時減少了 3%。有 3 種情況可以導致表鎖的使用,在討論表鎖的缺點之前,我們先用一點時間看看這 3 種情況:
* 運行 ALTER TABLE LOCKSIZE TABLE。這將導致 DB2 為隨后使用該表的所有 SQL 語句使用一個表鎖,直到 locksize 參數改回到 ROW。
* 運行 LOCK TABLE IN EXCLUSIVE MODE。這將導致表上立即上了一個 X 鎖。注意,在下一次提交(或回滾)的時候,這個表將被釋放,因此,如果您要運行一個測試,測試中每 N 行提交一次,那么就需要在每次提交之后重復執行 LOCK TABLE。
* 使用缺省鎖,但是讓 LOCKLIST 和 MAXLOCKS 數據庫配置參數的值比較小。當獲得少量的行鎖時,行鎖就會自動地逐漸升級為表鎖。
當然,所有這些的缺點就在于并發的影響:如果表上有一個 X 鎖,那么其他應用程序除非使用了隔離級別 UR(未提交的讀),否則都不能訪問該表。如果知道獨占訪問不會導致問題,那么就應該盡量使用表鎖。但是,即使您堅持使用行鎖,也應記住,在批量插入期間,表中可能存在數千個有 X 鎖的新行,所以就可能與其他使用該表的應用程序產生沖突。通過一些方法可以將這些沖突減至最少:
* 確保鎖的升級不會無故發生。您可能需要加大 LOCKLIST 和/或 MAXLOCKS 的值,以允許插入應用程序有足夠的鎖。
* 對于其他的應用程序,使用隔離級別 UR。
* 對于 V8 FixPak 4,或許也可以通過 DB2_EVALUNCOMMITTED 注冊表變量來減少鎖沖突:如果將該變量設置為 YES,那么在很多情況下,只能獲得那些符合某個謂詞的行上的鎖,而并不是獲得被檢查的所有行上的鎖。
* 發出一個 COMMIT 命令以釋放鎖,因此如果更頻繁地提交的話就足以減輕鎖沖突的負擔。
注意
* 在 V7 中,存在涉及 insert 和鍵鎖的并發問題,但是在 V8 中,由于提供了 type-2 索引,這些問題實際上已經不見了。如果要遷移到 V8 中來,那么應該確保使用帶 CONVERT 關鍵字的 REORG INDEXES 命令,以便將索引從 type-1 轉換為 type-2。
* 在 V7 中,插入過程中可能使用 W 或 NW 鎖,但是在 V8 中只有在使用了 type-1 索引或者隔離級別為 RR 的情況下才會出現這兩種鎖。因此,應盡可能避免這兩種情況。
* 一條 insert 所據有的鎖(通常是一個 X 鎖)通常不會受隔離級別的影響。例如,使用隔離級別 UR 不會阻止從插入的行上獲得鎖。然而,如果使用了 INSERT ... SELECT,則隔離級別將影響從 SELECT 獲得的鎖。
6. 日志記錄
缺省情況下,每條 insert 都會被記錄下來,以用于恢復。日志記錄首先被寫到內存中的日志緩沖池,然后再寫到日志文件,通常是在日志緩沖池已滿或者發生了一次提交時寫到日志文件的。對批量插入的日志記錄的優化實際上就是最小化日志記錄寫的次數,以及使寫的速度盡可能快。
這里首先考慮的是日志緩沖池的大小,這由數據庫配置參數 LOGBUFSZ 來控制。該參數缺省值為 8 頁或 32 K,這與大多數批量插入所需的理想日志緩沖池大小相比要小些。舉個例子,對于一個批量插入,假設對于每一行的日志內容有 200 字節,則在插入了 160 行之后,日志緩沖池就將被填滿。如果要插入 1000 行,因為日志緩沖池將被填滿幾次,再加上提交,所以大概有 6 次日志寫。如果將 LOGBUFSZ 的值增加到 64 頁(256K)或者更大,緩沖池就不會被填滿,這樣的話對于該批量插入就只有一次日志寫(在提交時)。通過使用更大的 LOGBUFSZ 可以獲得大約 13% 的性能提升。較大日志緩沖池的不利之處是,緊急事故恢復所花的時間可能要稍微長一點。