程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> DB2數據庫 >> DB2教程 >> DB2 最佳實踐: 使用 DB2 pureXML 管理 XML 數據的最佳實踐,第 2 部分:向 DB2 數據庫中添加 XML 數據指南

DB2 最佳實踐: 使用 DB2 pureXML 管理 XML 數據的最佳實踐,第 2 部分:向 DB2 數據庫中添加 XML 數據指南

編輯:DB2教程

高性能地插入 XML 文檔

DB2 VERSION 9.5 向把 XML 數據遷移進 DB2 表中提供了 3 個選項:插入,導入和裝載。從調優的角度來看插入和導入有類似的特點,因為導入實用工具事實上就是執行了一系列插入操作。

提示:裝載實用工具的優勢對 XML 和對關系型數據都一樣:數據不需要記錄日志而且是自動啟用並行來提高性能。 DB2 基於 CPUs 數目和表空間容器來判斷一個默認並行度。在其它方面,導入和插入的好處是數據可以在其它事務正在運行的時候插入到表中,所有約束都會被校驗,而且觸發器也會生效。

在某些情況下通過執行有中間過渡表的 ETL 操作來裝載 XML 數據到一個中間過渡表和填充實際目標表是有很多好處的。

你是否使用插入、導入或裝載,應用下面性能指南:

作為一個關鍵的前提條件,確保 DMS 表空間使用大頁面大小,比如 16KB 或者 32KB 。

即使如果你沒有在目標表上定義任何索引,為了高效的 XML 存儲訪問,DB2 pureXML 存儲機制會顯式的維護域和路徑索引。因此你應該提供足夠的緩沖池空間以支持索引讀取。

如果你有多個用戶定義 XML 索引,那麼通常在沒有任何數據插入的情況下定義它們要比之後再定義更好。在插入過程中,每個 XML 文檔將只被處理一次,以對所有 XML 索引生成索引輸入。然而,如果你在之後執行了多個 CREATE INDEX 語句,在這個 XML 列中的所有文檔都會被讀取多次。

另外,對插入和導入操作考慮下面的指南:

增加日志緩沖大小(LOGBUFSZ)和日志文件大小(LOGFILESIZ)有助於提高插入性能。這對 XML 插入非常重要,因為每行的數據量會比關系型數據要大很多。推薦使用一個快速 I/O 設備來存放日志。

如果你使用插入,一個小的 COMMITCOUNT 值參數也會影響性能。每 100 行或更多行一提交將比每行都提交擁有更好的性能。你可也可以省略 COMMITCOUNT 參數讓 DB2 在恰當的時候提交

ALTER TABLE < 表名 > APPEND ON 語句對這個表啟用追加模式。新數據被追加到表的最後而不是在現有頁面中搜索空閒空間。更多細節和指南見 DB2 文檔。

把大型 XML 文檔拆分成更小的片段

如果需要轉換或移動的 XML 文檔的數量很多,常常是把它們聯合成一個大型的 XML 文檔。處理一個大型文檔常常要比處理上千個瑣碎文件要容易。圖 9 顯示了一個 XML 文檔的結構,這個文檔使用根元素 <alltrades> 來壓縮一批 FpML 文檔。

提示:當你收到這樣一個“復合文檔”,你會希望把它分拆為單獨的交易並在 TRADES 表中的每一行都插入一個交易文檔。這將提供比存儲在一個復合文檔片段中更好的查詢和更新性能。


清單 1. 復合 XML 文檔結構
<FpML> 
  <trade> 
   ... 
  </trade> 
 </FpML> 
 <FpML> 
  <trade> 
   ... 
  </trade> 
 </FpML> 
 ... 
 <FpML> 
  <trade> 
   ... 
  </trade> 
 </FpML> 

DB2 可以添加最大 2GB 的 XML 文檔,而且你可以拆分 2GB 的文檔為更小的文檔,如圖 10 所示。在插入語句中的 XMLTABLE 函數為每個交易(每個 <FpML> 元素)在一行中生成一個單獨的 XML 類型列。“ ? ”在前面的子句中表示一個參數標記給這個語句中提供了一個 XML 文檔輸入。 cast (? as XML) 是用來表示 XML 類型的參數標記。

XML 數據模式需要解析,有良好格式的 XML 文檔有一個文檔節點(作為這個文檔中的唯一根元素的父節點)。這個文檔節點在一個 XML 文檔的文本表示上並不可見。從輸入文檔中抽取的交易子樹沒有文檔節點,而且不能作為一個有良好格式的文檔插入。因此,document{} 構造器為每一個抽取出來的交易創建一個文檔節點。


清單 2. 把大型輸入文檔拆分成單獨的交易文檔
INSERT INTO trades(tradedoc) 
 SELECT doc FROM 
 XMLTABLE ('$d/alltrades/FpML' passing cast(? as XML) as "d" 
  COLUMNS  
   doc XML PATH 'document{.}') AS X

你可能記得 TRADES 表也有一個整型的 tradeId 列。這列沒有被上述插入填充。基於你實際的應用需求,你可以定義 tradeId 列為自生成列。如果有 XML 列的表也包含關系型列,用從 XML 文檔中抽取的值來填充它們可能很有好處。這會在下一章中進行討論。

以混合方式存儲交易

在圖 11 中你可以看到一個 TRADES 表的第二個版本,在關系型列中保留了交易時間、交易類型和各個交易方的 IDs 。這是除了在 XML 列中的全部 FpML 文檔外的關系型數據,因此叫做混合存儲。

提示:抽取選擇的 XML 元素值插入到同一行的關系列中,XML 文檔可以滿座多種需求。關系型列可以很容易的被 SQL-only 訪問重要或經常訪問的數據條目、定義的主鍵、外鍵或其它約束,以及多列關系型索引(組合鍵)的定義。


清單 3. FpML 交易的混合存儲
create table trades2 (trdDate Date, trdType varchar(20), partyId1 integer, 
         partyId2 integer, tradedoc XML); 
 
 insert into trades2 
 select * 
 from xmltable('$d/FpML' passing cast(? as XML) as "d" 
 columns  
  tradeDate  date     path   'trade/tradeHeader/tradeDate', 
  tradetype  varchar(20)  path   'trade/*[2]/local-name(.)', 
  partyId1   integer    path   'party[@id="party1"]/partyId' , 
  partyId2   integer    path   'party[@id="party2"]/partyId', 
  doc     XML      path   'document{.}') 
   ) as t;

在圖 11 中的插入語句從文檔中為我們的關系型列正確的抽取了那些條目。因此,這些在關系型列中的值和 XML 列中的 XML 文檔是冗余的存儲。

提示:要確保 XML 列和關系型列的一致性,你可以把這個插入語句包裝進一個只把 FpML 文檔當作輸入參數的存儲過程中。如果所有的插入都通過存儲過程執行,那麼每一行的數據將保持一致。這同樣可以通過更新完成。應該避免插入和更新只對關系列進行操作。

插入時確保 XML 數據的品質

要確保 XML 文檔的數據質量的首選方法是在 DB2 中注冊一個正確的 XML 模式並在插入或更行的時候使用它來驗證文檔。在許多 XML 應用程序中,包括我們的 FpML 場景,XML 模式是隨時間持續發展變化的。為了避免驗證多種 FpML 文檔輸入,你肯需要在 DB2 中注冊多個 FpML 模式版本,比如版本 4.1、4.2、4.3 和最終的 FpML5.0 。

記住,在 DB2 中依靠一個模式來驗證 XML 文檔是可以選擇的。不過如果你不驗證,在性能上和功能上也沒有壞處。

提示:如果 XML 文檔在應用層面已經被驗證了,或者如果它們來自於同一個信任源,那麼在 DB2 中對他們進行驗證可能沒有必要。在這種情況下你可能希望不進行驗證就插入並節約驗證過程中的額外 CPU 開銷。

如果你選擇在 DB2 層驗證,你可以有很多方法。一個就是在一個插入語句中直接執行 XMLVALIDATE 函數,如圖 12 所示。這非常靈活而且允許你在基於每個文檔來控制驗證。可以依靠各自對應的 FpML 模式版本來驗證基於不同 FpML 標准版本的文檔,而且仍然存在相同的 XML 列中。


清單 4. 在插入語句中直接驗證交易文檔
 insert into trades (tradeID, tradedoc) 
  values (? , xmlvalidate(? according to XML schema ID matthias.fpml43))

這種方法的缺點是每個應用程序的每個插入語句都需要使用 XMLVALIDATE 函數並涉及正確的 XML 模式標識(這是在一個模式注冊時分配的)。換句話說,用這個方法來保證數據質量是分散的責任而且沒有集中控制。不過,DB2 有幾個功能可以在允許的 XML 數據上添加更多的集中控制。

你可以定義檢查約束來保證 XML 文檔在它們未能通過 XMLVALIDATE 函數正確驗證的情況下被拒絕。在圖 13 中的第一個檢查約束只有在使用 XMLVALIDATE 函數根據在 DB2 中注冊的某個 XML 模式驗證成功後才允許插入 XML 文檔。驗證失敗的插入將被拒絕。第二個檢查約束更強大,因為它只允許已經通過了被 IN 子句中列出的模式驗證過的文檔插入。如果在數據庫中注冊的僅有的 XML 模式是 matthias.fpml41、 matthias.fpml43、 matthias.fpml50 的話,這兩種驗證是等價的。


清單 5. 檢查約束拒絕未驗證文檔
 alter table trades add constraint chkvalidated1 
   check (tradedoc is validated) 
 
 alter table trades add constraint chkvalidated2 
   check (tradedoc is validated according to XMLschema id 
           IN (matthias.fpml41, matthias.fpml43, matthias.fpml50)

檢查約束他們自己不會執行或觸發模式驗證。他們只檢查是否一個被插入(或更新)的文檔已經被正確的驗證過。

提示:不過,你可以使用 BEFORE 觸發器來自動強制進行文檔驗證(圖 14)。為了避免兩次驗證,我們推薦你在插入語句中顯式的進行驗證,或使用一個觸發器,但不要同時用。


清單 6. BEFORE 觸發器強制進行文檔驗證
create trigger tr1 before insert on trades 
 referencing new as n 
 for each row mode db2sql 
 begin atomic 
 set (n.tradedoc) = XMLvalidate(n.tradedoc according to 
                     XMLschema id matthias.fpml43 ); 
 end

如果你已經在你的數據庫中根據不同的模式驗證了不同的文檔,你可能碰到這樣的情形,當你想找到用於驗證一個文檔的模式;或者,你希望找到一個確定模式來驗證的所有文檔。標量函數 XMLXSROBJECTID 可以為你做這些。你用一個 XML 文檔(或者其中任意一個片段)作為一個數據被返回用於驗證這個文檔的 XML 模式的 ID 。有了這個 ID,你可以在 DB2 的 XML 模式庫(XSR)找到 XML 模式。考慮下面的情況:


清單 7. 使用 XMLXSROBJECTID 函數
select XMLxsrobjectid(tradedoc) 
 from trades 
 where XMLexists...; 
 
 select T.tradedoc 
 from trades T, syscat.xsrobjects X 
 where XMLxsrobjectid(T.tradedoc) = X.objectid 
 and X.objectname = 'fpml43';

更多關於管理的個 XML 模式的文檔的信息,請參見參考資源部分。

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