詳解DB2中自定義XML存儲(chǔ)及其使用環(huán)境
原創(chuàng)【51CTO經(jīng)典譯文】使用IBM DB2 for z/OS和DB2 for Linux,UNIX和Windows (LUW),那就沒有問題,下面讓我們一起回顧一下什么時(shí)候使用XML存儲(chǔ),以及如何自定義XML存儲(chǔ)的一些***實(shí)踐吧!
為了形象地說明,我將使用一個(gè)XML文檔,內(nèi)容如下:
- <order OrderID="9001" OrderDate="2009-10-18">>
- <customerID>26914</customerID>
- <item id="LK-486">
- <name>Magic Potion</name>
- <size>300ml</size>
- <price>19.99</price>
- </item>
- <item id="VF-145">
- <name>Crystal Ball, Deluxe</name>
- <color>crystal clear</color>
- <price>295.00</price>
- </item>
- </order>
它展示了一個(gè)包括訂單ID,日期,客戶ID和其它條目的訂單XML文檔,注意有些條目的描述方式有所不同,如size和color。我們假設(shè)需要在DB2中管理許多與此類似的XML文檔。
如何拆分和重組XML
我在另一篇文章“15個(gè)DB2 pureXML性能***實(shí)踐”中談到了你應(yīng)該明智地選擇文檔的粒度,實(shí)際上就是要將存儲(chǔ)在DB2中的XML文檔與應(yīng)用程序的業(yè)務(wù)邏輯對(duì)象和主要的訪問粒度匹配。
在我們的例子中,假設(shè)訂單變化非常頻繁,訂單內(nèi)的條目讀取,添加或刪除是最關(guān)鍵的操作,需要***的性能,在這種情況下,你可以考慮將訂單文檔拆分,將每一個(gè)條目作為一個(gè)獨(dú)立的文檔存儲(chǔ)到DB2表的每一行中,這個(gè)存儲(chǔ)方法(與原來的完整存儲(chǔ)訂單文檔的方法相比)的好處是它使得操作所存儲(chǔ)的數(shù)據(jù)更容易,更快速:
可以使用單行讀取檢索一個(gè)條目,不用從一個(gè)完整的訂單文檔中抽取條目了;
可以通過刪除表中的行簡單地從訂單中刪除一個(gè)條目,不再需要操作完整的訂單文檔;
可以迅速插入一個(gè)新條目到訂單中,這時(shí)也不需要操作完整的訂單文檔。
這種輕松添加和移除訂單條目的功能在DB2 9 for z/OS中尤其有價(jià)值,因?yàn)檫@個(gè)版本不支持在現(xiàn)有XML文檔中添加或刪除元素。
下面的代碼顯示了一個(gè)表的定義,以及拆分一個(gè)訂單文檔的INSERT語句,相關(guān)的列分別存儲(chǔ)訂單ID,客戶ID,訂單日期和一個(gè)條目流水號(hào)。
- CREATE TABLE items(ordID INTEGER, custID INTEGER,
- odate DATE, seqNo INTEGER, item XML);
- INSERT INTO items(ordID, custID, odate, seqno, item)
- SELECT T.ordID, T.custID, T.odate, T.seqno, XMLDOCUMENT( T.item)
- FROM
- XMLTABLE('$d/order/item' PASSING cast(? AS XML) "d"
- COLUMNS
- ordID INTEGER PATH '../@OrderID',
- custID INTEGER PATH '../customerID'
- odate DATE PATH '../@OrderDate',
- seqNo FOR ORDINALITY,
- item XML PATH '.') AS T;
條目信息是以XML格式存儲(chǔ)的,因?yàn)闂l目可能有不同的元素和屬性,如:
- ORDID CUSTID ODATE SEQNO ITEM
- ----- ----- ------ ----- -----
- 9001 26914 10/18/2009 1 <item id="LK-486">
- <name>Magic Potion</name>
- <size>300ml</size>
- <price>19.99</price>
- </item>
- 9001 26914 10/18/2009 2 <item id="VF-145">
- <name>Crystal Ball, Deluxe</name>
- <color>crystal clear</color>
- <price>295.00</price>
- </item>
- 2 record(s) selected.
INSERT語句包括一個(gè)XMLTABLE函數(shù),這個(gè)函數(shù)從輸入XML文檔抽取插入items表中的值,它將會(huì)拆分輸入XML文檔,生成獨(dú)立條目的文檔。XMLTABLE函數(shù)包括一個(gè)參數(shù),通過它,應(yīng)用程序可以傳遞一個(gè)訂單文檔,使用XPath表達(dá)式$d/order/item,XMLTABLE函數(shù)為輸入文檔的每一個(gè)條目生成一行數(shù)據(jù),然后抽取訂單ID,客戶ID和訂單日期,特殊的列定義FOR ORDINALITY為產(chǎn)生的每一行打上編號(hào)。XMLDOCUMENT函數(shù)確保每一個(gè)條目片段可以作為一個(gè)獨(dú)立的XML文檔插入。
上面的代碼顯示了使用INSERT語句插入XML文檔后items表中的數(shù)據(jù),下面的代碼顯示了如何重建原始的訂單文檔,XMLELEMENT和XMLATTRIBUTES函數(shù)使用items表中相關(guān)列的值構(gòu)建的頂部文檔,XMLAGG函數(shù)組合所有條目,***形成一個(gè)完整的訂單文檔。注意,XMLAGG在seqno列上包括一個(gè)可選的ORDER BY子句,這樣可以確保還原后的訂單文檔和原始文檔中的條目顯示順序是一致的。
- SELECT XMLELEMENT(name "order",
- XMLATTRIBUTES(ordID AS "OrderID", odate as "OrderDate"),
- XMLELEMENT(name "customerID", custID)
- XMLAGG(item ORDER BY seqno) )
- FROM items
- WHERE ordID = 9001
- GROUP BY ordID, odate, custID;
使用生成列
DB2 9.7 for LUW中新的IBM DB2 pureXML特性允許你與數(shù)據(jù)庫分區(qū)功能(Database Partitioning Feature,DPF),范圍分區(qū)表和多維集群(MDC)表一起使用XML列,但分區(qū)或集群鍵必須由相關(guān)的列組成。前面你已經(jīng)看到了如何使用INSERT和XMLTABLE從XML文檔抽取值到相關(guān)的列中,你可以使用這些關(guān)聯(lián)列對(duì)表進(jìn)行分區(qū)或集群。如果你更喜歡在程序中使用簡單的INSERT語句,并且不知道如何抽取數(shù)據(jù)時(shí),那你可以考慮使用一個(gè)生成的列。
DB2 9.7在用戶定義函數(shù)(UDF)中支持XML參數(shù),允許你定義生成的列,使用插入的XML文檔中的值自動(dòng)填充。下面的代碼顯示了一個(gè)UDF,它接受一個(gè)XML文檔作為輸入,如前面例子中的訂單文檔,這個(gè)UDF使用XMLCAST和XMLQUERY函數(shù)抽取輸入文檔的OrderDate屬性:
- CREATE FUNCTION extractDate(doc XML)
- RETURNS DATE
- LANGUAGE SQL CONTAINS SQL
- NO EXTERNAL ACTION DETERMINISTIC
- RETURN XMLCAST(XMLQUERY('$d/order/@OrderDate'
- PASSING doc AS "d") AS DATE);
你可以在SELECT查詢和其它SQL語句中使用這個(gè)UDF,但也要定義一個(gè)生成列,對(duì)于下面的示例,假設(shè)檢索和插入完整的訂單是最關(guān)鍵的操作,在這種情況下,完整地存儲(chǔ)訂單文檔是***的選擇。下面的代碼定義了一個(gè)使用XML列存儲(chǔ)訂單的表,并自動(dòng)抽取訂單日期填充到關(guān)聯(lián)的列(odate)中。一條INSERT語句現(xiàn)在可以簡單地插入一個(gè)XML文檔到order列中,不需要考慮抽取值到關(guān)聯(lián)列中:
- CREATE TABLE orders(
- order XML,
- odate DATE GENERATED ALWAYS AS (extractDate(order)));
如果你連續(xù)不斷地存儲(chǔ)許多訂單,可能需要對(duì)舊訂單進(jìn)行歸檔,這個(gè)時(shí)候使用范圍分區(qū)是***的選擇,下面的代碼顯示了表order2是通過按odate列的值進(jìn)行分區(qū)的,odate列則產(chǎn)生自XML列,同樣,你可以使用生成的列作為分區(qū)數(shù)據(jù)庫的分配鍵,也可以作為MDC表的集群鍵:
- CREATE TABLE order2(
- order XML,
- odate DATE GENERATED ALWAYS AS (extractDate(order)) NOT NULL)
- PARTITION BY RANGE (odate)
- (PART q109 STARTING('01-01-2009') ENDING ('03-31-2009') INCLUSIVE,
- PART q209 ENDING ('06-30-2009') INCLUSIVE,
- PART q309 ENDING ('09-30-2009') INCLUSIVE,
- PART q409 ENDING ('12-31-2009') INCLUSIVE);
控制XML存儲(chǔ)
自定義XML存儲(chǔ)有許多好處,將大型XML文檔拆分成多個(gè)小文檔,將會(huì)使操作XML數(shù)據(jù)變得更加容易和高效,使用UDF定義生成列可以簡化XML值抽取到關(guān)聯(lián)列,使用生成列還可以幫助你管理分區(qū)數(shù)據(jù)庫,范圍分區(qū)表,或MDC表中的XML。
原文出處:http://www.ibm.com/developerworks/data/library/dmmag/DMMag_2009_Issue3/Tips/index.html
原文名:Customizing XML storage in DB2
作者:Matthias Nicola
【編輯推薦】
- 在DB2中正確導(dǎo)出LOB數(shù)據(jù)
- DB2外部文件格式淺析
- DB2數(shù)據(jù)庫設(shè)計(jì)的三個(gè)建議
- 解析DB2與非DB2數(shù)據(jù)庫之間遠(yuǎn)程復(fù)制
- DB2數(shù)據(jù)庫基本操作指令30條