影響 LOAD 性能的選項
LOAD 工具與其他數據移動工具比較起來的一大優勢就是提供卓越的性能,這主要是由於 LOAD 對數據的加載時采取數據頁級別的處理,這繞過了數據庫管理系統的多個處理層次,因此可以極大的提高性能。除了 LOAD 工具本身的這一特點之外,我們還可以通過合理的設置 LOAD 的一些選項來進一步提高其性能。下面列出一些影響 LOAD 性能的選項及其合理設置的建議。
CPU_PARALLELISM n
此選項用於指定一個 LOAD 同時使用 n 個 CPU 來並發的處理 LOAD,在 LOAD 處理的數據量較大並且操作系統的負載不高的情況下,可以通過此參數指定多個 CPU 並發的執行構建表過程中的解析、轉換、格式化等內容來提高效率。如果同時啟動了多個 LOAD 工具要注意所有 LOAD 工具指定的此參數最好不要超過操作系統中邏輯 CPU 的總數(在此指定的 CPU 是 LCPU- 即邏輯 CPU)。
此選項不設置,則 DB2 會根據當前操作系統中 CPU 的數量自動的分配 CPU 數量。
DATA BUFFER buffersize
此選項用於指定 LOAD 工具能夠使用的數據緩存的最大值,單位是 4k 。我們可以想象,在處理的數據量很大,且在不超過操作系統空閒物理內存的情況下,我們為 LOAD 分配越多的數據緩存那麼 LOAD 的性能將會越好。但是此值設置受到數據庫的參數 UTIL_HEAP_SZ 限制。 由於使用 UTIL_HEAP_SZ 的工具有多個,所以為某個 LOAD 分配的數據緩存一般建議不要超過 UTIL_HEAP_SZ 的 50%,在實際設置時,最好根據 UTIL_HEAP_SZ 的實際情況來確定,這可以通過觀察數據庫快照中工具堆使用的大小和高水位大小來判斷。
另外,此選項並非單純的設置的越大越好,因為在數據緩存設置的最夠大以後即使再增加其大小也不會有利於性能的提升,因為性能的瓶頸已經不在是緩存了。所以需要在實際生產中做多次的測試以找到一個最適合的值。
DISK_PARALLELISM n
此選項用於指定 LOAD 工具可以利用向表空間中多個容器執行並發 I/O 的能力來提高性能。根據表空間中容器的數量做適當設置即可。
ModifIEd by ANYORDER
此文件修飾符,可以使用輸入文件中預設好的排序結果來提高性能。如果輸入的文件來自於 export 工具中使用一定排序謂詞到處的數據,那麼性能會得到較大提升(可以提升幾倍到幾十倍)。且此文件修飾符可以用於各種輸入的文件格式。
ModifIEd by FASTPARSE
此文件修飾符通過降低對輸入數據的檢查來提升性能,如果輸入的數據與目標表的結構、類型上並無差別,那麼可以通過設置此選項來提升性能。此文件修飾符只能用於 ASC 或 DEL 格式的文件。
ModifIEd by NOROWWARNINGS
如果預期在 LOAD 過程會有大量的 warning 出現,那麼可以使用此文件修飾符來提升性能。
SAVECOUNT
此選項可以降低 LOAD 在設置一致性恢復點上面的負載,在處理大數據量的情況下可以使用此選項來提升性能,根據處理數據量的情況來合理的設置此值。如需要加載的數據為 1000 萬行,那麼可以將此值設置為 10000 。此文件修飾符不能與 anrorder 文件修飾符同時使用。
USER tablespace
當需要 LOAD 的表中存在大量索引需要構建時,且表或索引本身所在的表空間不不是很大的情況下,使用此選項制定一個系統臨時表空間,來提高其數據構建的性能。
使用游標(cursor)來提高 LOAD 性能
LOAD 工具在加載數據的時候,輸入的數據除了可以是 ixf、asc 和 del 類型的文件之外,還可以是游標(curosr)。如果需要將一個表中的數據保存到另外一張表中,且對應的列的類型是一致的,那麼我們就可以使用游標的方式來實現數據的移動。游標方式之所以能提高數據加載的效率是因為數據不需要以文件的方式保存到磁盤上,而是直接從源數據表到達目標數據表中,這樣就可以節省了兩次 I/O 過程(導出的數據以文件保存到磁盤的過程和加載數據時從磁盤上讀取數據文件的過程),從而大大提高數據處理的效率。
示例如下:
創建 sql 文件 test.sql, 其內容如下:
清單 1. SQL 語句 —— test.sql
declare cursor mycur for select * from tab1name;
load from mycur of cursor insert into tab2name;
注:在游標聲明中的 SQL 語句根據應用的需要自主確定其內容,load 的選項也可以根據各種需求自主確定。
在 DB2 環境下執行如下命令:
清單 2. 執行 SQL 語句
db2 connect to dbname
db2 – tvf test.sql
代碼頁的轉換
在不同的數據庫間移動數據經常會出現代碼頁不一致的情況,這就需要根據不同的情況分別處理。如果保存數據的文件是 asc 或 del 格式,那麼需要使用文件修飾符:codepage,此選項指定數據的源數據庫的代碼頁的值。
清單 3. 示例 1 —— DEL 文件
LOAD from test of del modifIEd by codepage=819 insert into tabname
如果保存數據的文件是 ixf 格式,那麼不需要 load 工具使用任何選項,且在數據加載的過程中會自動的完成代碼頁的轉換。如果在執行代碼頁轉換的工程中造成數據格式的變化而導致了加載無法成功,則使用 forcein 的文件修飾符,實例如下:
清單 4. 示例 2 —— IXF 文件
LOAD from test of ixf modifIEd by forcein insert into tabname
注:當加載的數據在表結構完全相同的情況下還出現了一些非空字符或字符被截斷錯誤,可以選擇使用 ixf 格式並指定 forcein 文件修飾符來避免這種問題。
錯誤行的定位
在 DB2 V8 及 DB2 V9.1 環境下,執行 load 加載數據的過程中可能會出現某些行的部分列的數據不符合目標表類型或格式的要求,從而導致其被截斷或被拒絕,那麼找到源數據庫中的故障行和故障列分析其故障原因就比較重要。但是在這種故障情況下輸出的錯誤信息可能如下:
表單 5. 執行錯誤信息
SQL3125W 因為數據比目標數據庫列長,所以第 "F4-6" 行第 "5"
列中的字符數據被截斷。
SQL3110N 實用程序已完成處理。從輸入文件讀了 "13" 行。
SQL3519W 開始裝入一致點。輸入記錄數 = "13" 。
SQL3520W “裝入一致點”成功。
SQL3515W 在時間 "2009-01-04 11:18:53.301919",實用程序已經完成了 "LOAD" 。
SQL3107W 消息文件中至少有一條警告消息。
其中故障的行的標識為“ F4-6 ”,這表示 id 為 4 的 CPU 處理的第 6 行的數據出現了故障,那麼通過這個信息我們是無法從源文件中找到故障行的,我們只能通過總的行號標識來找到故障行,所以在這種情況下只能通過單 CPU 的處理來找到故障行。
這就需要將 load 工具的 CPU_PARALLELISM 選項設置為 1,保證 load 在加載數據的過程中始終只適用一顆 CPU,那麼此時行標識中 CPU 部分始終會是“ F0 ”,而行部分則就是總的行數了。
在 DB2 V9.5 中會同時輸出 SQL3227W 的消息來幫助定位總的行數,避免了上述問題, 示例如下。
表單 6. 執行錯誤詳細信息
SQL3125W 因為數據比目標數據庫列長,所以第 "F4-6" 行第 "5"
列中的字符數據被截斷。
SQL3227W 記錄標記 "F4-6" 指的是用戶記錄號 "16" 。
SQL3110N 實用程序已完成處理。從輸入文件讀了 "53" 行。
SQL3519W 開始裝入一致點。輸入記錄數 = "53" 。
SQL3520W “裝入一致點”成功。
SQL3515W 在時間 "2009-01-04 11:18:53.301919",實用程序已經完成了 "LOAD" 。
SQL3107W 消息文件中至少有一條警告消息。
無法與查詢並行執行的處理
在執行 LOAD 的同時,一般情況下不能對 LOAD 工具的目標表執行任何的訪問。但有如下的特殊情況。
如果針對目標表的查詢是先執行的,那麼不論指定了什麼選項,LOAD 工具總是不能執行的。直到針對目標表的查詢結束,LOAD 工具才能執行。
如果針對目標表的查詢是後執行的,也就是首先執行了 LOAD 工具,在 LOAD 工具的運行期間再執行查詢,那麼只要 LOAD 工具指定了 allow read Access 選項,查詢語句就可以後續的執行了。
所以在無法准確的確定 LOAD 工具與查詢語句的執行順序的情況下,而且又需要並發的執行查詢,那麼 LOAD 工具不是一個好的工具,最好的方式是使用 import 工具替代 LOAD 工具,此時並行查詢可以隨時啟動。
觀察正在執行的 LOAD 狀態
當一個或多個 LOAD 工具正在執行的情況下,如果需要詳細的觀察這些工具的執行情況,那麼使用命令“ list utilitIEs ”可以實現。示例如下。
清單 7. LOAD 命令執行狀態
>db2 list utilitIEs show detail
標識 = 5
類型 = LOAD
數據庫名稱 = SAMPLE
分區號 = 0
描述 = OFFLINE LOAD DEL AUTOMATIC INDEXING INSERT COPY NO YUAN .T1
開始時間 = 2009-01-05 10:44:57.203583
狀態 = 執行
調用類型 = 用戶
進度監視: 階段號 = 1 描述 = SETUP 總計工作 = 0 bytes 已完成的工作 = 0 bytes
開始時間 = 2009-01-05 10:44:57.203592
階段號 [ 當前 ] = 2 描述 = LOAD 總計工作 = 2174631 rows
已完成的工作 = 1106547 rows 開始時間 = 2009-01-05 10:44:57.248663
上面的輸出中只有兩個階段,如果有目標表有索引存在的話還會有第三個階段 -BUILD 階段。評估正在執行著的 LOAD 工具的剩余時間主要通過比較“總計工作”和“已完成的工作”這個兩個值大小和比例。
使用 LOAD 觀察表的狀態
我們知道,觀察數據庫的狀態可以通過快照或 list db 命令,觀察表空間的狀態可以通過快照或 list tablespace 命令,而觀察表的狀態我們通常只知道快照可以反映表被訪問的一些情況,而當表不可用的時候,需要獲得表的故障狀態時候卻沒有對應的 list 命令可以使用。
那麼這種情況下,我們可以使用 LOAD QUERY 工具來實現。示例如下:
清單 8. 觀察表的狀態
C:\Program Files\IBM\SQLLIB\BIN>db2 "select * from t1"
DEPTNUMB DEPTNAME MANAGER DIVISION LOCATION
-------- -------------- ------- ---------- -------------
SQL0668N 不允許對表 "YUAN.T1" 執行操作,原因碼為 "3" 。 SQLSTATE=57016
C:\Program Files\IBM\SQLLIB\BIN>db2 load query table t1
SQL3501W 由於禁用數據庫正向恢復,因此表所駐留的表空間將不被置於備份暫掛狀態。
SQL3109N 實用程序正在開始從文件 "e:\t1.out" 裝入數據。
SQL3500W 在時間 "2009-01-05 10:52:56.661277",實用程序在開始 "LOAD" 。
SQL3519W 開始裝入一致點。輸入記錄數 = "0" 。
SQL3520W “裝入一致點”成功。
SQL3005N 處理被中斷。
SQL3532I Load 實用程序當前正處於 "LOAD" 階段。
讀取行數 = 0
跳過行數 = 0
裝入行數 = 0
拒絕行數 = 0
刪除行數 = 0
落實行數 = 0
警告數 = 0
表狀態: 裝入暫掛
由此,我們可以判斷,當前的表不能被訪問,是由於處於“裝入暫掛”的狀態,那麼我們可以通過 LOAD 工具將 LOAD 執行完 (restart) 或終止 (terminate) 將這個故障處理掉再訪問這個表。
使用 LOAD 快速的清空一張表
在不需要一張表中的數據的時候,我需要將其清空。而做這個工作我們可以選擇多種辦法:
刪除表中數據:delete from tablename
不記 log 刪除表中數據: alter table tabname activate not logged initially;delete from tablename
修改表不記錄 log 方式:alter table tabname activate not logged with empty table
LOAD 的 replace 方式:load from empfile of del replace into tabname
注:文件 empfile 為空
“ 1 ”的方式可用性非常差,會消耗大量的時間和 log 空間,一般不使用。除非需要有選擇的刪除數據的時候。
“ 2 ”的方式可以使用,但是過於麻煩,尤其還要注意兩條語句必須在同一事務中執行。
“ 3 ”的方式是一種較好的快速清空數據表的方式。
“ 4 ”的方式也是一種較好的快速清空數據表的方式,而且對於“ 3 ”來說,過程更加可控,因為 load 支持 restart 和 terminate 等故障控制選項。
所以推薦使用“ 4 ”的方式來快速的清空一張表。