|
XML與數(shù)據(jù)庫
2.0 XML是數(shù)據(jù)庫嗎?(Is XML a Database?) 如果僅按數(shù)據(jù)庫這個(gè)術(shù)語的本質(zhì)來看,XML文件就是數(shù)據(jù)庫,它是數(shù)據(jù)的集合。在許多方面看起來它和其他文件沒什么區(qū)別 -- 無論如何,每個(gè)文件都含有某種類型的數(shù)據(jù)。作為一種“數(shù)據(jù)庫”格式,XML有一些優(yōu)勢(shì):例如,它是自描述的(所用的標(biāo)記描述了數(shù)據(jù)的結(jié)構(gòu)和類型,盡管缺乏語義),可交換的(portable)(Unicode),能夠以樹型或圖形結(jié)構(gòu)描述數(shù)據(jù)。同樣它也有缺點(diǎn),例如,它顯得有些繁瑣,由于要對(duì)它進(jìn)行解析和文本轉(zhuǎn)換,所以數(shù)據(jù)訪問速度較慢。 一個(gè)更有用的問題就是在較為寬松的意義上,XML及其周邊技術(shù)是否可以算作“數(shù)據(jù)庫” -- 數(shù)據(jù)庫管理系統(tǒng)(DBMS)。答案是“在某種程度上是(sort of)”。從正面來說,XML提供了許多數(shù)據(jù)庫所具備的東西:存儲(chǔ)(XML文檔), 模式(DTD, XML schema,RElAX NG 等等), 查詢語言(XQuery, XPath, XQL, XML-QL, QUILT等等),編程接口(SAX, DOM,JDOM)等等。從反面來說,它缺少一些作為實(shí)用的數(shù)據(jù)庫所應(yīng)具備的特性:高效的存儲(chǔ),索引,安全,事務(wù)和數(shù)據(jù)一致性,多用戶訪問,觸發(fā)器,在查詢多個(gè)文件等等。 因此,盡管在數(shù)據(jù)量小、用戶少和性能要求不太高的環(huán)境下,可以將XML文檔用作數(shù)據(jù)庫,但是卻不適用于用戶量大、數(shù)據(jù)集成度高以及性能要求高的作業(yè)環(huán)境。 XML適合于用作所謂“數(shù)據(jù)庫”的一個(gè)好例子就是 .ini文件 -- 它包含應(yīng)用程序的配置信息。與其寫一個(gè)處理以逗號(hào)分隔(comma-delimited)的文件的解析器,開發(fā)一種小型的XML語言并寫一個(gè)解釋它的 SAX程序要容易的多。此外,XML允許使用嵌套的實(shí)體,而逗號(hào)分隔的文件(comma-delimited files)很難做到這點(diǎn)。然而,說它就是數(shù)據(jù)庫還很勉強(qiáng),因?yàn)樗蔷€性讀寫的,而且僅用在程序開始和結(jié)束時(shí)。 比較適合于XML數(shù)據(jù)庫的一些復(fù)雜的數(shù)據(jù)集就是個(gè)人通訊錄(名字,電話號(hào)碼,地址等),或用于描述瀏覽器書簽以及用Napster偷來的MP3。然而,由于dBase和Access之類的數(shù)據(jù)庫物美價(jià)廉,即使在這種情況下似乎也沒有多少理由把XML文件作為數(shù)據(jù)庫使用。XML的唯一真正好處就是數(shù)據(jù)的可交換性(portable),由于有越來越多的工具可以用來對(duì)數(shù)據(jù)庫進(jìn)行XML序列化(serializing),這一點(diǎn)好處似乎也要打些折扣。 3.0 為什么要用數(shù)據(jù)庫?(Why Use a Database?) 例如,你有個(gè)電子商務(wù)的應(yīng)用,將XML用作數(shù)據(jù)交換。那么你的數(shù)據(jù)最好有個(gè)非常規(guī)則的結(jié)構(gòu)并且可供非XML程序使用。還有,XML文檔所用的某些東西如實(shí)體和編碼對(duì)你來說并不重要 --總之,你感興趣的是數(shù)據(jù),而不是它在XML內(nèi)如何存儲(chǔ)。在這種情況下,你大概需要一個(gè)關(guān)系型數(shù)據(jù)庫以及在XML和數(shù)據(jù)庫之間轉(zhuǎn)換數(shù)據(jù)的軟件。如果你的應(yīng)用程序是面向?qū)ο蟮?,你甚至還需要一個(gè)在數(shù)據(jù)庫或XML中存取這些對(duì)象的系統(tǒng)。 另一方面,假如你要從一些結(jié)構(gòu)松散的XML文檔建立一個(gè)網(wǎng)站。你不但要管理這個(gè)網(wǎng)站,還要提供站點(diǎn)內(nèi)容搜索。你的文檔看起來結(jié)構(gòu)比較松散,其中的實(shí)體的使用對(duì)你來說可能更重要,因?yàn)樗鼈兪俏臋n結(jié)構(gòu)的重要部分。這種情況下,你也許需要一個(gè)原生XML數(shù)據(jù)庫(native XML database)或內(nèi)容管理系統(tǒng)(content management system)。這使你可以保持文檔的物理結(jié)構(gòu),支持文件級(jí)的事務(wù)處理,以及使用XML Query語言進(jìn)行查詢。 4.0 數(shù)據(jù)和文檔 (Data versus Documents) (歷史背景:我在xml-dev郵件列表上第一次聽說data-centric和document-centric這些術(shù)語,不知道是誰發(fā)明的,但是我在1997的消息中發(fā)現(xiàn)有使用document-centric的,從1998年以后這兩個(gè)術(shù)語都有使用。) 4.1 以數(shù)據(jù)為中心的文檔 (Data-Centric Documents) 以數(shù)據(jù)為中心的文檔的特點(diǎn)是結(jié)構(gòu)相當(dāng)規(guī)整,數(shù)據(jù)粒度精細(xì)(fine-grained data)(即最小的獨(dú)立數(shù)據(jù)單位只存在于PCDATA元素或?qū)傩赃@一級(jí)別),很少或沒有混合內(nèi)容。除非在對(duì)文檔進(jìn)行驗(yàn)證的時(shí)候,同級(jí)元素或PCDATA的出現(xiàn)次序一般來說并不重要。 以數(shù)據(jù)為中心的文檔中的這類數(shù)據(jù)可以來自數(shù)據(jù)庫(此時(shí)要輸入給XML)或在數(shù)據(jù)庫之外(此時(shí)要將其存入數(shù)據(jù)庫)。前者的一個(gè)例子就是關(guān)系數(shù)據(jù)庫現(xiàn)存的大量數(shù)據(jù);而從測(cè)量系統(tǒng)采集并轉(zhuǎn)化為XML的科研數(shù)據(jù)就是后者的例子。 例如,下面的銷售訂單就是以數(shù)據(jù)為中心的: <SalesOrder SONumber="12345"> 例如,下面是個(gè)描述航班信息的文檔: <FlightInfo> <Flights> 以文檔為中心的文檔通常是以XML手工寫成,或從其他格式(如RTF, PDF, SGML)轉(zhuǎn)換到XML,與以數(shù)據(jù)為中心的文檔不同,它們的來源通常不是數(shù)據(jù)庫。(將數(shù)據(jù)插入到模板而得到的文檔是以數(shù)據(jù)為中心的;更多信息請(qǐng)看4.1節(jié)末尾部分)。將各種格式轉(zhuǎn)換為XML的軟件信息,請(qǐng)參閱XML軟件相關(guān)鏈接。 例如,下面這個(gè)產(chǎn)品說明是以文檔為中心的: <Product> <Intro> <Description> <Para>The turkey wrench, which comes in <i>both right- and left- 除此之外,弄清文件的這兩種特點(diǎn)有助于選擇數(shù)據(jù)庫的類型。一般來說,將數(shù)據(jù)存儲(chǔ)于傳統(tǒng)的數(shù)據(jù)庫,例如關(guān)系型,面向?qū)ο笮突驅(qū)哟涡蛿?shù)據(jù)庫。這可由第三方的中間件完成或由數(shù)據(jù)庫本身提供內(nèi)在支持。對(duì)于后者,該數(shù)據(jù)庫被稱作支持XML的(XML-enabled)。文檔可被存儲(chǔ)在原生(native)XML數(shù)據(jù)庫(專為存儲(chǔ)XML而設(shè)計(jì)的數(shù)據(jù)庫)或內(nèi)容管理系統(tǒng)(建在原生XML數(shù)據(jù)庫之上專門用來管理文檔的程序)。 這些原則并不是絕對(duì)的。如果對(duì)XML特有的功能不很看重,數(shù)據(jù),特別是半結(jié)構(gòu)化的數(shù)據(jù)可以存儲(chǔ)在原生XML數(shù)據(jù)庫,文檔也可以存儲(chǔ)到傳統(tǒng)數(shù)據(jù)庫。何況傳統(tǒng)數(shù)據(jù)庫與原生XML數(shù)據(jù)庫之間的界限越來越模糊,傳統(tǒng)數(shù)據(jù)庫增加了原生XML的能力,而原生XML數(shù)據(jù)庫增加了對(duì)文檔存儲(chǔ)在外部(通常為關(guān)系型)數(shù)據(jù)庫的支持。 本文剩下的部分就有關(guān)數(shù)據(jù)(第5節(jié))和文檔(第6節(jié))的存儲(chǔ)和讀取的策略與問題展開討論。關(guān)于最新的XML數(shù)據(jù)庫產(chǎn)品,請(qǐng)見XML數(shù)據(jù)庫產(chǎn)品。 5.0 數(shù)據(jù)的存取(Storing and Retrieving Data) 對(duì)于后者,文檔的結(jié)構(gòu)必須完全符合映射所要求的結(jié)構(gòu)。由于通常不易做到這點(diǎn),使用這種策略的產(chǎn)品一般要和XSLT一起使用。在數(shù)據(jù)轉(zhuǎn)換到數(shù)據(jù)庫之前,先將文件按照映射所要求的結(jié)構(gòu)進(jìn)行轉(zhuǎn)換,然后轉(zhuǎn)存數(shù)據(jù)。相應(yīng)地,數(shù)據(jù)從數(shù)據(jù)庫中取出以后,結(jié)果文件要被轉(zhuǎn)換成應(yīng)用程序所需的結(jié)構(gòu)。 5.1 映射[XML]文件Schema到數(shù)據(jù)庫Schema (Mapping Document Schemas to Database Schemas) 這種方法的一個(gè)后果是能否保證文件有“往返車票” -- 將文件中的數(shù)據(jù)存入數(shù)據(jù)庫后,又從數(shù)據(jù)庫中的數(shù)據(jù)重新構(gòu)建文件,得到的文件往往和原來的文件不同(哪怕從最簡單的角度來講)。這種情形是否可以接受取決于你的要求,在選擇軟件時(shí)要考慮到這一點(diǎn)。 將一個(gè)XML文件的schema映射到數(shù)據(jù)庫的schema有兩種方法:基于表格的映射和對(duì)象-關(guān)系映射。 5.1.1 基于表格的映射 (Table-Based Mapping) <database> 基于表格的映射對(duì)存取關(guān)系型數(shù)據(jù)比較適用,比如在兩個(gè)關(guān)系型數(shù)據(jù)庫之間轉(zhuǎn)換數(shù)據(jù)。其明顯不足就是不適于格式不符的XML文件。 5.1.2 對(duì)象-關(guān)系映射 (Object-Relational Mapping) (所謂“對(duì)象-關(guān)系映射”有些名不副實(shí)。因?yàn)閷?duì)象樹可以被直接映射到面向?qū)ο笮秃蛯哟涡蛿?shù)據(jù)庫,然而,但是由于大多數(shù)使用這種映射方式的主流產(chǎn)品使用的其實(shí)是關(guān)系型數(shù)據(jù)庫,所以“對(duì)象-關(guān)系映射”也就廣為人知。) 我們?cè)诶斫膺@種映射所用的對(duì)象模型的時(shí)候要知道,這個(gè)對(duì)象模型不是文件對(duì)象模型(DOM)。所有XML文件的DOM都是一樣的,而上述描述文件數(shù)據(jù)的模型對(duì)于每個(gè)DTD所定義的XML文件都不一樣,例如,上述銷售訂單的模型是一個(gè)由四個(gè)類所組成的對(duì)象樹--SalesOrder, Customer, Item, 和Part, 如下圖所示: SalesOrder 元素 --- 屬性 (根據(jù)Sun的 Java Architecture for XML Binding,XML文件與對(duì)象的綁定通常被稱為XML數(shù)據(jù)綁定(XML data binding),有些產(chǎn)品支持XML數(shù)據(jù)綁定,其中許多還可以在對(duì)象和數(shù)據(jù)庫之間進(jìn)行數(shù)據(jù)交換,更多的信息,請(qǐng)看 XML數(shù)據(jù)綁定相關(guān)資源 XML Data Binding Resources.) 各種產(chǎn)品對(duì)對(duì)象-關(guān)系映射的具體支持各不相同。例如: 所有產(chǎn)品都支持從復(fù)合元素類型到類,以及從簡單元素類型和屬性(attributes)到[類的]屬性(properties)的映射。 當(dāng)使用基于表格的映射的XML文件有多個(gè)表格組成時(shí),這個(gè)包裝元素就相當(dāng)于<database>元素,他的存在只是為了滿足 XML 文件只能有一個(gè)根元素的要求。少數(shù)產(chǎn)品允許你就像指定包裝元素那樣,在較低的層次上指定[某些元素是否被映射 -譯注]。 大多數(shù)產(chǎn)品允許你說明將[對(duì)象的]屬性(properties)映射到XML文件中的屬性(attribute)還是子元素。某些產(chǎn)品還允許你混合使用屬性和子元素,其他的只允許你使用兩者之一。 5.2 查詢語言(Query Languages) 這個(gè)問題的長久解決方案就是設(shè)計(jì)一種可以返回XML[文件]的查詢語言。目前來看(2002年11月),大多數(shù)這種語言都依賴于在模板中嵌入 SELECT 語句。到 XQuery 最后定稿時(shí)這個(gè)局面有望得到改變,正如主流的數(shù)據(jù)庫產(chǎn)品提供商已經(jīng)做的那樣。不幸的是,幾乎所有的XML查詢語言(包括 XQuery1.0 和 SQL/XML的最初發(fā)布版本)對(duì)文件都是只讀的,所以短期來說,最需要的是能夠插入、更新、刪除數(shù)據(jù)的手段。(從長遠(yuǎn)來看,XQuery 和 SQL/XML 將會(huì)增加這種功能。) 5.2.1 基于模板的查詢 (Template-Based Query) <?xml version="1.0"?> <?xml version="1.0"?> 可以將返回結(jié)果放在輸出文件中的任何地方,包括作為后續(xù)SELECT語句的參數(shù)。 5.2.2 基于SQL的查詢語言 (SQL-Based Query Languages) 除了這些私有語言以外,2000年一些公司聯(lián)合提出了 SQL 的 XML 擴(kuò)展標(biāo)準(zhǔn),現(xiàn)在已經(jīng)成為被稱為 SQL/XML 的 ISO SQL 標(biāo)準(zhǔn)的一部分;最終可望于2003年得到批準(zhǔn)。 SQL/XML 引入了一種 XML 數(shù)據(jù)類型,并且為 SQL 增加了幾個(gè)函數(shù),可以從關(guān)系型數(shù)據(jù)構(gòu)造 XML 元素和屬性。 例如,下面的查詢 SELECT Orders.SONumber, <Order SONumber="123"> 5.2.3 XML Query Languages 對(duì)于XQuery,基于表格的映射或?qū)ο?關(guān)系型映射都可以使用。當(dāng)使用基于表格的映射時(shí),各個(gè)表格被視為單獨(dú)的文件,像SQL中的一樣, 這些表格的結(jié)合(joints)則在查詢[語句]本身中指明。如果使用的是對(duì)象-關(guān)系型映射,各個(gè)表格的層次被當(dāng)作單個(gè)文件,而[表格的]結(jié)合在映射中說明。對(duì)于大多數(shù)關(guān)系數(shù)據(jù)庫而言,似乎基于表格的映射更為常用,這是因?yàn)樗膶?shí)現(xiàn)似乎更簡單些,SQL的用戶對(duì)此也更為熟悉。 如果使用XPath在多個(gè)表格中進(jìn)行查詢,就必須使用對(duì)象-關(guān)系映射,這是因?yàn)閄Path不支持多個(gè)文檔的聯(lián)合。因此,如果使用基于表格的映射,也許每次只對(duì)一個(gè)表格進(jìn)行查詢最好。 5.3 原生XML數(shù)據(jù)庫的數(shù)據(jù)存儲(chǔ)(Storing Data in a Native XML Database) 將數(shù)據(jù)存儲(chǔ)在原生XML數(shù)據(jù)庫中的第二個(gè)理由是讀出速度。根據(jù)XML數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù)的物理方式的不同,數(shù)據(jù)的讀出速度可以做到比關(guān)系型數(shù)據(jù)庫[的讀取速度]快得多。其原因是,原生XML數(shù)據(jù)庫對(duì)整個(gè)文件一起進(jìn)行物理存儲(chǔ),和[表示]文件各個(gè)部分的物理(而不是邏輯)指針可采用同一存儲(chǔ)策略。這就可以不使用連接(joins)或只使用物理連接讀取文件,無論哪種情況都比關(guān)系型數(shù)據(jù)庫所用的邏輯聯(lián)結(jié)要快。 以上述銷售訂單文件為例。在關(guān)系型數(shù)據(jù)庫中,它可能被存為四個(gè)表格 -- SalesOrders, Items, Customers, 和 Parts -- 讀取文件時(shí)需要將這些表格結(jié)合起來。在原生XML數(shù)據(jù)庫中,整個(gè)文件可被存儲(chǔ)在磁盤的一個(gè)地方,在讀取文件或其片斷時(shí)只需要一次查找和一次讀取操作。關(guān)系數(shù)據(jù)庫在讀取數(shù)據(jù)時(shí)則需要四次查找以及至少四次讀取操作。 這樣做的一個(gè)明顯缺點(diǎn)就是,只有數(shù)據(jù)的讀取順序和寫入磁盤的順序相同時(shí),才可以提高速度。如果你想要的數(shù)據(jù)視圖不同,比如只想要客戶及其訂單列表,性能可能比關(guān)系數(shù)據(jù)庫更差。所以,如果你的應(yīng)用中是單個(gè)數(shù)據(jù)視圖為主,為了提高性能,才可以考慮將數(shù)據(jù)存儲(chǔ)到原生XML數(shù)據(jù)庫。 將數(shù)據(jù)存儲(chǔ)在原生XML數(shù)據(jù)庫中的第三個(gè)理由是你想利用XML的獨(dú)有特性,如執(zhí)行XML查詢。由于今天以數(shù)據(jù)為中心的應(yīng)用幾乎沒有這樣做的,而且關(guān)系數(shù)據(jù)庫正在逐步支持XML查詢語言,這個(gè)理由越來越不充分。 將數(shù)據(jù)存儲(chǔ)在原生XML數(shù)據(jù)庫中的一個(gè)問題是,大多數(shù)原生數(shù)據(jù)庫只能以XML[的形式]返回?cái)?shù)據(jù)。(支持元素和屬性到應(yīng)用程序變量綁定的只是少數(shù))。如果你的應(yīng)用程序需要另一種數(shù)據(jù)格式(很有可能),使用數(shù)據(jù)之前必須先解析XML。對(duì)本地的應(yīng)用程序而言顯然是個(gè)缺點(diǎn),而這種前期準(zhǔn)備在(比如)ODBC中就不存在。對(duì)于將XML作為數(shù)據(jù)載體使用的分布式應(yīng)用程序而言,這個(gè)問題不很嚴(yán)重,因?yàn)椴还苡玫氖悄姆N數(shù)據(jù)庫,這種前期工作必須要有。 5.4 數(shù)據(jù)類型,空值,字符集,諸如此類 (Data Types, Null values,Character Sets, and All That Stuff) 5.4.1 數(shù)據(jù)類型 Data Types 至于軟件如何確定該進(jìn)行怎樣的轉(zhuǎn)換各不相同,常見的有兩種方法。第一種方法是軟件根據(jù)數(shù)據(jù)庫模型來確定數(shù)據(jù)類型,因?yàn)樗谶\(yùn)行時(shí)總是可用的。(而XML模型在運(yùn)行時(shí)就不一定有,甚至根本就不存在)。第二種方法就是由用戶明確指定數(shù)據(jù)類型,比如映射信息。它可以由用戶寫出,或者自動(dòng)從數(shù)據(jù)庫模型或XML 模型中產(chǎn)生。 類型轉(zhuǎn)換時(shí)的另一個(gè)問題是,究竟能夠識(shí)別(從 XML 轉(zhuǎn)換)或創(chuàng)建什么文本格式。大多數(shù)情況下,能夠被識(shí)別為特定數(shù)據(jù)類型的文本格式數(shù)目很有限,比如某個(gè)JDBC驅(qū)動(dòng)程序支持單一的、特定的格式。日期看起來最容易出問題,因?yàn)樗母袷娇赡芊浅6?。而?shù)字在各種語言中的格式也不盡相同,也有可能出問題。 5.4.2 二進(jìn)制數(shù)據(jù) (Binary Data) 二進(jìn)制數(shù)據(jù)的最大問題在于數(shù)據(jù)轉(zhuǎn)換產(chǎn)品對(duì)它的支持不夠,所以要檢查你的軟件是否支持。另一個(gè)問題是,大部分(全部?)數(shù)據(jù)轉(zhuǎn)換產(chǎn)品都不存儲(chǔ)符號(hào)和實(shí)體聲明。這樣,將 XML 中的數(shù)據(jù)轉(zhuǎn)換到數(shù)據(jù)庫中時(shí),與某些實(shí)體對(duì)應(yīng)的符號(hào)就會(huì)丟失。(關(guān)于符號(hào)的更多信息詳見 XML 標(biāo)準(zhǔn)的 4.7 部分)。 5.4.3 空數(shù)據(jù) (Null Data) XML也支持這種空數(shù)據(jù)的概念(通過可選(optional)元素或?qū)傩?。如果一個(gè)可選元素或?qū)傩缘闹禐榭眨筒粫?huì)包含在文件內(nèi)。而在數(shù)據(jù)庫中,值為零長度字符串的屬性和空元素并不是null:它們的值為零長度的字符串。 當(dāng)你將XML文檔的結(jié)構(gòu)映射到數(shù)據(jù)庫(或反過來)時(shí),你當(dāng)特別留意,可選元素類型或[空值]屬性會(huì)被映射到允許空值的字段(nullable columns),反之亦然。如果不是這樣的話,可能會(huì)產(chǎn)生插入錯(cuò)誤(當(dāng)轉(zhuǎn)換數(shù)據(jù)到數(shù)據(jù)庫時(shí))或非法文件錯(cuò)誤(從數(shù)據(jù)庫中取出數(shù)據(jù)時(shí))。 與數(shù)據(jù)庫專業(yè)相比,XML社區(qū)對(duì)null含義的表示法更為自由-- 特別是許多XML用戶都認(rèn)為零長度字符串的屬性和空元素是“空(null)”的,所以你應(yīng)該檢查一下你的軟件是如何處理這種情況的。有些軟件為用戶提供了選擇,可以定義XML中如何表示"null",以及支持XML Schema中的 xsi:null屬性。 5.4.4 字符集 (Character Sets) 5.4.5 處理指令和注釋 (Processing Instructions and Comments) 5.4.6 對(duì)標(biāo)記的存儲(chǔ) (Storing Markup) <description> <b>Confusing example:</b> <foo/> 另外,如果實(shí)體引用被擴(kuò)展了,數(shù)據(jù)轉(zhuǎn)換軟件無法區(qū)別標(biāo)記和實(shí)體。例如,如果上述例子在數(shù)據(jù)庫中按照下面的形式存儲(chǔ),則軟件就無法知道<b> , </b> 和<foo/>到底是標(biāo)記還是文本。 <b>Confusing example:</b> <foo/>解決這個(gè)問題的長久之計(jì)就是支持XML的數(shù)據(jù)庫(XML-aware database),在那里,對(duì)真正的標(biāo)記和看起來很像標(biāo)記的東西的處理方式是不同的。非XML應(yīng)用程序處理XML時(shí),總是會(huì)出現(xiàn)這種問題。 5.5 從關(guān)系[數(shù)據(jù)庫]Schema產(chǎn)生DTD或相反 (Generating DTDs from Relational Schema and Vice Versa) 從DTD產(chǎn)生關(guān)系模型(或相反)的最簡單方法就是直接借助于對(duì)象-關(guān)系映射,它有幾個(gè)可選特性。對(duì)于面向?qū)ο蟮臄?shù)據(jù)庫也有相似的途徑。(關(guān)于每種方法的逐步演示,請(qǐng)看Mapping DTDs to Databases.)。 從DTD產(chǎn)生關(guān)系模型: 對(duì)每個(gè)復(fù)合數(shù)據(jù)類型, 創(chuàng)建一個(gè)表格和主鍵字段 為每個(gè)表創(chuàng)建一種元素類型。 更加嚴(yán)重的問題是,XML文件所用的數(shù)據(jù)“模型”通常和數(shù)據(jù)庫中所用的高效率的模型不同,(實(shí)際上更為復(fù)雜)。請(qǐng)看如下XML片斷: <Customer> <Address>元素就是包裝元素(wrapper element)的典型例子。采用包裝元素的原因有二:首先,這種結(jié)構(gòu)使得文檔更容易理解;其次,它可作為一種數(shù)據(jù)類型使用。例如,可以將<Address>元素傳給一個(gè)例程,該例程可以將所有地址轉(zhuǎn)換為Address對(duì)象,不管它出現(xiàn)在哪里。 雖然包裝元素在XML中很有用,但被映射到數(shù)據(jù)庫中的時(shí)候會(huì)增加額外的結(jié)構(gòu),很容易出問題。因此,在產(chǎn)生關(guān)系模型之前,一般應(yīng)將其從DTD中除去。由于DTD一般是不允許改變的,而在映射是又不包含包裝元素,所以往往會(huì)導(dǎo)致實(shí)際文檔與數(shù)據(jù)轉(zhuǎn)換軟件所要求的文檔不匹配。對(duì)此可以在運(yùn)行時(shí)轉(zhuǎn)換文件(比如使用XSLT):數(shù)據(jù)被轉(zhuǎn)到數(shù)據(jù)庫之前去掉包裝元素,轉(zhuǎn)出后在加上它。 盡管有這些不足,上述步驟還是為DTD和關(guān)系模型之間的轉(zhuǎn)換提供了一個(gè)起點(diǎn),對(duì)于大型系統(tǒng)尤為如此。 6.0 文件的存取 (Storing and Retrieving Documents) 6.1 將文件存儲(chǔ)于文件系統(tǒng) (Storing Documents in the File System) 6.2 將文件存儲(chǔ)于BLOB (Storing Documents in BLOBs) 如果以BLOB的形式存儲(chǔ)XML文件,即使數(shù)據(jù)庫不支持對(duì)XML的檢索,你也很容易實(shí)現(xiàn)自己的XML檢索。方法之一是創(chuàng)建兩個(gè)表:索引表(DB2中的side table)和文件表。文件表包含一個(gè)主鍵和一個(gè)存儲(chǔ)文件的BLOB字段,索引表內(nèi)有一個(gè)已建立索引值字段以及一個(gè)外來鍵指向文件表中的主鍵。 文件被存在數(shù)據(jù)庫中之后,就可以搜索所有已建索引的元素和屬性實(shí)例。每個(gè)實(shí)例及文件的主鍵都存于索引表中。這樣已建立索引的字段使應(yīng)用程序可以快速檢索某個(gè)元素或?qū)傩灾挡@取相應(yīng)的文件。 舉例來說,假如你有一些符合下列DTD的文件,希望建立作者的索引: <!ELEMENT Brochure (Title, Author, Content)> Authors Brochures SELECT Brochure 6.3 原生XML數(shù)據(jù)庫 (Native XML Databases) 顯然原生XML數(shù)據(jù)庫最適于存儲(chǔ)以文檔為中心的文件。這是由于原生XML數(shù)據(jù)庫保留了文件[元素?]順序、處理指令、注釋、CDATA塊以及實(shí)體引用等,而支持XML的數(shù)據(jù)庫(XML-enabled database)無法做到。此外,原生數(shù)據(jù)庫支持XML查詢語言,你可以對(duì)它提這樣的問題:“找出所有第三段內(nèi)包含粗體字的文件”,用SQL顯然很難進(jìn)行這樣的查詢。 原生XML數(shù)據(jù)庫還適用于存儲(chǔ)那些“天然格式”為XML的文件,而不管這些文件包含什么內(nèi)容。例如,電子商務(wù)系統(tǒng)消息所用的XML文件。盡管這些文件可能是以數(shù)據(jù)為中心的,而作為消息來說它們的天然格式是XML。這樣當(dāng)它們被存入消息隊(duì)列后,建立在原生XML數(shù)據(jù)庫上的消息隊(duì)列使用起來更為方便。原生XML數(shù)據(jù)庫保留了XML的特性比如XML查詢語言,通常能更快地取出整條消息。Web cache是這類應(yīng)用的另一個(gè)例子。 原生XML數(shù)據(jù)庫的其他用途是存儲(chǔ)半結(jié)構(gòu)化數(shù)據(jù)、在某種特定情形下提高存取速度以及存儲(chǔ)沒有DTD的文件(良構(gòu)的文件)。前兩種已經(jīng)在5.3 原生XML數(shù)據(jù)庫的數(shù)據(jù)存儲(chǔ)中敘述過。而后一種用非XML的數(shù)據(jù)庫是做不好的。也就是說,原生XML數(shù)據(jù)庫無須事先配置即可接受和存儲(chǔ)任何XML文件。將XML文件中的數(shù)據(jù)轉(zhuǎn)換到關(guān)系型或面向?qū)ο笮蛿?shù)據(jù)庫必須首先建立映射和數(shù)據(jù)庫模型。無須事先配置對(duì)于搜索引擎之類的應(yīng)用程序來說是有利的,因?yàn)闆]有任何DTD能適用于所有搜索文檔。 6.3.1 什么是原生數(shù)據(jù)庫(Native XML Database)? 有一個(gè)接近的定義(出自XML:DB mailing list的一個(gè)成員)這樣定義原生XML數(shù)據(jù)庫(native XML database): 它為 XML 文檔(而不是文檔中的數(shù)據(jù))定義了一個(gè)(邏輯)模型,并根據(jù)該模型存取文件。這個(gè)模型至少應(yīng)包括元素、屬性、PCDATA 和文件順序。這種模型的例子有XPath數(shù)據(jù)模型、XML Infoset 以及 DOM 所用的模型和SAX 1.0的事件。 它以 XML 文件作為其基本(邏輯)存儲(chǔ)單位,正如關(guān)系數(shù)據(jù)庫以表中的行作為基本(邏輯)存儲(chǔ)單位。 定義的第二個(gè)部分是說原生數(shù)據(jù)庫的基本存儲(chǔ)單位是 XML 文件??雌饋硭坪跻部纱鎯?chǔ) XML 文件片斷,但幾乎所有的原生 XML 數(shù)據(jù)庫都是以文件方式存儲(chǔ)的。 (基本存儲(chǔ)單位就是可以容納一份數(shù)據(jù)的最低級(jí)的上下文 (context),相當(dāng)于關(guān)系數(shù)據(jù)庫中的行。它的存在并不妨礙以更小的數(shù)據(jù)單位來讀取數(shù)據(jù),比如文件片斷或個(gè)別元素,同樣也不影響將不同文件中的片斷進(jìn)行組合。從關(guān)系數(shù)據(jù)庫的術(shù)語來講,相當(dāng)于數(shù)據(jù)雖然以行的形式存放,并不意味著無法讀取某個(gè)字段的值,或從現(xiàn)有的數(shù)據(jù)行創(chuàng)建新一行數(shù)據(jù)。) 該定義的第三部分講的是底層的數(shù)據(jù)存儲(chǔ)格式并不重要。確實(shí)如此,正如關(guān)系數(shù)據(jù)庫所使用的物理存儲(chǔ)格式與數(shù)據(jù)庫是不是關(guān)系型之間毫無關(guān)系。 6.3.2 原生XML數(shù)據(jù)庫的結(jié)構(gòu) (Native XML Database Architectures) 6.3.2.1 基于文本的原生XML數(shù)據(jù)庫(Text-Based Native XML Databases) 索引對(duì)所有基于文本的原生XML數(shù)據(jù)庫來說都是一樣的,它可以使查詢引擎很方便地跳到XML文件內(nèi)的任何地方。這就可以大大提高數(shù)據(jù)庫存取文件或文件片斷的速度。這是因?yàn)閿?shù)據(jù)庫只需進(jìn)行一次檢索、磁頭定位,再假如所讀的文件在磁盤上是連續(xù)[存儲(chǔ)]的話,只需一次讀盤就可讀出整個(gè)文件或文件片斷。相反,如果像關(guān)系數(shù)據(jù)庫或基于模型的原生XML數(shù)據(jù)庫那樣,文件由各個(gè)部分組合而成,就必須要進(jìn)行多次查找定位和多次讀盤動(dòng)作。 從這個(gè)意義上講,基于文本的原生XML數(shù)據(jù)庫與層次結(jié)構(gòu)的數(shù)據(jù)庫很相似,當(dāng)存取預(yù)先定義好層次的數(shù)據(jù)的時(shí)候,它比關(guān)系數(shù)據(jù)庫更勝一籌。和層次結(jié)構(gòu)的數(shù)據(jù)庫一樣,當(dāng)以其他形式比如轉(zhuǎn)置層次存取數(shù)據(jù)時(shí),原生XML數(shù)據(jù)庫也會(huì)遇到麻煩。這個(gè)問題的嚴(yán)重程度尚未可知,很多關(guān)系數(shù)據(jù)庫都使用邏輯指針,使相同復(fù)雜度的查詢以相同的速度完成。由此看來這確實(shí)是個(gè)問題。 6.3.2.2 基于模型的原生XML數(shù)據(jù)庫 (Model-Based Native XML Databases) (Mark Birbeck 在 1998年12月的 XML-L 郵件列表中描述了一個(gè)建立在關(guān)系型數(shù)據(jù)庫上的簡單的、基于 模型的原生 XML 數(shù)據(jù)庫系統(tǒng),該系統(tǒng)用了5個(gè)表 - 屬性定義、元素/屬性關(guān)聯(lián)、內(nèi)容模型定義、屬性值、元素值 (PCDATA 或指向其它元素的指針),以及只包含元素、屬性、文本和文件順序的模型。參見標(biāo)題為 "Record ends, Mixed content, and storing XML documents on relational database" 和 "storing XML documents on relational database"的信件。) 建立在其他數(shù)據(jù)庫之上的基于模型的原生XML數(shù)據(jù)庫的文件存取性能與這些數(shù)據(jù)庫相似,原因顯而易見:其存取要依賴這些數(shù)據(jù)庫。但是這個(gè)數(shù)據(jù)庫,特別是建立在其他數(shù)據(jù)庫之上的原生XML數(shù)據(jù)庫的設(shè)計(jì)有很大的變化余地。例如直接以 DOM 方式進(jìn)行對(duì)象-關(guān)系映射的數(shù)據(jù)庫系統(tǒng)在獲取節(jié)點(diǎn)的子元素時(shí)必須單獨(dú)執(zhí)行 SELECT 語句。另一方面,這種數(shù)據(jù)庫大多對(duì)存取模型和軟件作了優(yōu)化。例如 Richard Edwards 在 system for storing the DOM in a relational database一文中曾經(jīng)描述只用一個(gè)SELECT語句就可獲取任意文件片斷(或整個(gè)文件)。 使用專用存儲(chǔ)格式的基于模型的原生XML數(shù)據(jù)庫如果以文件的存儲(chǔ)順序讀取文件,其性能與基于文本的原生XML數(shù)據(jù)庫相似。這是因?yàn)檫@種數(shù)據(jù)庫大多在節(jié)點(diǎn)間使用了物理指針,這樣其讀取性能和讀取文本差不多。(究竟哪個(gè)快一些要取決于數(shù)據(jù)格式。如果返回文本格式,顯然基于文本的系統(tǒng)要快一些;如果希望返回的是DOM,假如該模型很容易映射到DOM,則基于模型的系統(tǒng)更快。) 與基于文本的原生XML數(shù)據(jù)庫一樣,如果數(shù)據(jù)的讀取順序和存儲(chǔ)順序不同,基于模型的原生XML數(shù)據(jù)庫很容易出現(xiàn)性能上的問題。這兩種類型的數(shù)據(jù)庫到底哪個(gè)快一些仍不是很清楚。 6.3.3 原生XML數(shù)據(jù)庫的特性 (Features of Native XML Databases) 6.3.3.1 文件集 (Document Collections) 作為另一個(gè)例子,假設(shè)你想把公司的所有產(chǎn)品的說明書存儲(chǔ)在原生XML數(shù)據(jù)庫中,在這種情形下,你要先定義一個(gè)層次結(jié)構(gòu)。比如,為每種產(chǎn)品定義一個(gè)集合,并在其中為每種產(chǎn)品說明書的每個(gè)章節(jié)都指定一個(gè)集合。 這些集合是否被允許嵌套取決于所用的數(shù)據(jù)庫。 6.3.3.2 查詢語言 (Query Languages) 將來大多數(shù)原生XML數(shù)據(jù)庫大概都要支持W3C的XQuery。 6.3.3.3 更新和刪除 (Updates and Deletes) 6.3.3.4 事務(wù)、鎖定和并發(fā) (Transactions, Locking, and Concurrency) 例如用戶手冊(cè)分成幾個(gè)章節(jié),每個(gè)章節(jié)都是一個(gè)文件,這時(shí)并發(fā)問題就小一些,因?yàn)閮蓚€(gè)作者同時(shí)對(duì)同一章節(jié)進(jìn)行更新的情況不大可能發(fā)生。而另一方面,如果整個(gè)公司的客戶數(shù)據(jù)都放在同一個(gè)文件中(糟糕的設(shè)計(jì)),文件級(jí)的鎖定很容易造成災(zāi)難性的后果。 將來,大多數(shù)的原生數(shù)據(jù)庫應(yīng)該會(huì)提供文件片斷級(jí)的鎖定。 6.3.3.5 應(yīng)用程序接口 (Application Programming Interfaces ,APIs) 對(duì)以數(shù)據(jù)為中心的應(yīng)用來說比較有趣的特性是將應(yīng)用程序變量與返回文檔的特定元素或?qū)傩韵嚓P(guān)聯(lián)的能力。這就免除了應(yīng)用程序?yàn)闃?gòu)件內(nèi)部數(shù)據(jù)對(duì)象而不得不對(duì)文檔進(jìn)行解析的工作,隨著XML數(shù)據(jù)綁定技術(shù)的應(yīng)用越來越多,看起來這個(gè)特性會(huì)得到廣泛支持。 雖然大多數(shù)原生XML數(shù)據(jù)庫都提供有自己的API,但是XML:DB.org已經(jīng)開發(fā)出一種與供應(yīng)商無關(guān)的XML數(shù)據(jù)庫API (vendor-neutral XML database API),許多原生XML數(shù)據(jù)庫已經(jīng)支持它,而且有些非原生的[XML]數(shù)據(jù)庫也可能支持。不管這個(gè)或其他的API是否會(huì)成為工業(yè)標(biāo)準(zhǔn),此類API的廣泛采用最終是不可避免的。 大多數(shù)原生數(shù)據(jù)庫還有將查詢結(jié)果通過 HTTP 返回的能力。 6.3.3.6 “往返車票”(Round-Tripping) (對(duì)于以數(shù)據(jù)為中心的應(yīng)用來說,由于它主要關(guān)心的是元素、屬性、文本以及層次順序,這種“往返車票”顯得不是很重要。能夠在XML文件和數(shù)據(jù)庫之間交換數(shù)據(jù)的軟件都可以處理這些往返問題,如果同級(jí)元素的順序?qū)σ詳?shù)據(jù)為中心的應(yīng)用程序來說很重要,在有限幾種情況下也可以保留這種順序。但是由于它[指一般的交換軟件--譯者注]一般不保留兄弟元素的順序,也不確保原樣保持處理指令、注釋以及物理結(jié)構(gòu)(實(shí)體引用、CDATA等等),所以不適于以文檔為中心的應(yīng)用。) 所有原生XML數(shù)據(jù)庫都能夠在元素、屬性、CDATA和文件順序的級(jí)別上為文件提供“往返車票”,至于究竟能達(dá)到什么程度取決于數(shù)據(jù)庫。一般來說,基于文本的原生XML數(shù)據(jù)庫能夠原樣存取XML文件,而基于模型的原生XML數(shù)據(jù)庫只能在文件模型的級(jí)別上原樣存取XML文件。對(duì)于特別小的文檔模型,意味著比普通的XML原樣存取的級(jí)別低。 由于你的應(yīng)用程序要求決定了應(yīng)當(dāng)在哪個(gè)級(jí)別原樣存取,所以對(duì)原生XML數(shù)據(jù)庫的選擇余地可能很大,也可能很小。 6.3.3.7 外部數(shù)據(jù) (Remote Data) 6.3.3.8 索引 (Indexes) 6.3.3.9 外部實(shí)體存儲(chǔ) (External Entity Storage) 例如,假設(shè)文檔中包含一個(gè)外部實(shí)體用來調(diào)用一個(gè)當(dāng)前天氣報(bào)告的CGI程序。如果將這個(gè)文件用于提供天氣預(yù)報(bào)的網(wǎng)頁,那么將這個(gè)實(shí)體展開就是錯(cuò)誤的,因?yàn)榫W(wǎng)頁中提供的不是即時(shí)的數(shù)據(jù)。相反,如果文件是氣象歷史資料的一部分,那么不展開它反而是不對(duì)的,否則文件總是含有當(dāng)前的數(shù)據(jù)而不是歷史資料了。 再看另外一個(gè)例子,假設(shè)一個(gè)產(chǎn)品手冊(cè)只包含指向手冊(cè)中其他章節(jié)的外部實(shí)體引用。如果這些章節(jié)又被其他文件(比如該產(chǎn)品的另一種型號(hào)的手冊(cè))使用,那么展開這些引用就不對(duì)了,因?yàn)檫@會(huì)造成同一個(gè)章節(jié)有多份拷貝。 我不知道原生XML數(shù)據(jù)庫如何處理這個(gè)問題。最理想的當(dāng)然是允許你根據(jù)不同情況指定是否展開外部實(shí)體引用。 6.3.4 規(guī)范化,引用完整性和可伸縮性 (Normalization, Referential Integrity, and Scalability) 6.3.4.1 規(guī)范化 (Normalization) 在進(jìn)一步討論規(guī)范性之前,需要指出對(duì)許多以文檔為中心的文件這不是大問題。例如有一些描述公司產(chǎn)品信息的文件,通常各個(gè)文件的公用數(shù)據(jù)很少--比如版權(quán)聲明、公司地址和電話號(hào)碼、產(chǎn)品標(biāo)志等等,其數(shù)量相對(duì)來說太小了,幾乎沒有人考慮它的存儲(chǔ)規(guī)范性。(但是,其他種類的文檔可能有許多重疊內(nèi)容,有必要進(jìn)行規(guī)范化)。 與關(guān)系型數(shù)據(jù)庫一樣,原生XML數(shù)據(jù)庫并不要求你一定要規(guī)范你的數(shù)據(jù),用原生XML數(shù)據(jù)庫你也很容易設(shè)計(jì)出一個(gè)糟糕的存儲(chǔ)結(jié)構(gòu)。所以在將文件存入原生XML數(shù)據(jù)庫之前,你應(yīng)仔細(xì)考慮文檔的結(jié)構(gòu)。(與關(guān)系型數(shù)據(jù)庫相比,原生XML數(shù)據(jù)庫在這點(diǎn)有些優(yōu)勢(shì)。因?yàn)樵鶻ML數(shù)據(jù)庫沒有數(shù)據(jù)庫模式,你可以同時(shí)以多種模式存儲(chǔ)相似的文件,不過為了簡化事務(wù)處理,你可能需要重新設(shè)計(jì)查詢并轉(zhuǎn)換你的文件(這相對(duì)并不重要)) 原生XML數(shù)據(jù)庫的規(guī)范化和關(guān)系型數(shù)據(jù)庫的規(guī)范化差不多一樣:你的文檔的設(shè)計(jì)要保證不會(huì)有重復(fù)數(shù)據(jù)。兩者的不同在于XML支持多值屬性而(大多數(shù))關(guān)系型數(shù)據(jù)庫不支持。這樣就有可能以一種在關(guān)系型數(shù)據(jù)庫中無法實(shí)現(xiàn)的方式來“規(guī)范”原生XML數(shù)據(jù)庫的數(shù)據(jù)。 例如銷售訂單,它含有頭信息比如訂單編號(hào)、日期和客戶代碼,還有具體項(xiàng)目如零件號(hào)、數(shù)量和總價(jià)。在關(guān)系型數(shù)據(jù)庫中,頭信息和具體項(xiàng)目必須存在于不同的表內(nèi)。而在原生XML數(shù)據(jù)庫中,這些信息可以存儲(chǔ)在同一個(gè)文件內(nèi),不會(huì)產(chǎn)生冗余,因?yàn)閄ML與生俱來就支持一個(gè)父元素內(nèi)包含多個(gè)子元素。 不幸的是,現(xiàn)實(shí)當(dāng)中的規(guī)范化可沒這么簡單。例如你想要銷售訂單包含客戶信息如合同名稱、收貨和付款地址,該怎樣做? 你有兩種選擇:第一,你可以在銷售訂單中復(fù)制一份客戶信息,結(jié)果帶來數(shù)據(jù)冗余和其他問題;第二,你可以單獨(dú)存儲(chǔ)客戶信息,在銷售訂單中提供一個(gè)指向客戶信息文件的XLink,或者在查詢時(shí)再將這兩個(gè)文件連接起來。這就要求對(duì)XLink的支持(雖然正在計(jì)劃,但大多并不支持)或者查詢語言要支持聯(lián)合[joins](同樣并不總能如愿)。 在實(shí)踐當(dāng)中答案尚不明確。實(shí)際當(dāng)中出于性能的考慮,數(shù)據(jù)并不總是規(guī)范的,所以有一些不規(guī)范的XML數(shù)據(jù)并不像初看起來那么糟糕,不過你必須做出抉擇。如果你存儲(chǔ)的是以文檔為中心的文件并且在相當(dāng)程度上做到了規(guī)范化,比如將章節(jié)或過程單獨(dú)存儲(chǔ)并將它們連接起來創(chuàng)建最終用戶所用的文件,那么原生XML數(shù)據(jù)庫可能就是一個(gè)不錯(cuò)的解決方案,尤其是它能提供別的數(shù)據(jù)庫中所沒有的特性比如XML查詢語言。如果你要存儲(chǔ)的文件是以數(shù)據(jù)為中心的,而原生XML數(shù)據(jù)庫能夠改進(jìn)應(yīng)用程序的性能,或者它提供的半結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ),而在別的數(shù)據(jù)庫中是無法實(shí)現(xiàn)的,你也應(yīng)當(dāng)用原生XML數(shù)據(jù)庫。如果你只不過想在原生XML數(shù)據(jù)庫內(nèi)實(shí)現(xiàn)一個(gè)關(guān)系型數(shù)據(jù)庫,你就應(yīng)該反思一下,為什么不把關(guān)系型數(shù)據(jù)庫列為首選。 6.3.4.2 引用完整性 (Referential Integrity) 在關(guān)系型數(shù)據(jù)庫中,引用完整性意味著確保外部鍵指向合法的主鍵,也就是說,對(duì)每個(gè)外部鍵都要檢查相應(yīng)的主鍵記錄。在原生XML數(shù)據(jù)庫中,引用完整性意味著XLink或其他專有鏈接機(jī)制指向合法的文件或文件片斷。 XML 文件中的指針有多種形式:ID/IDREF 屬性,key/keyref 域(在 XML Schema 中定義),XLink 以及各種私有機(jī)制。后者包括語言相關(guān)的“referencing”元素和屬性,例如 XML Schema 中 <element>元素的 ref 屬性,以及特定數(shù)據(jù)庫的鏈接機(jī)制。而語言相關(guān)的“referencing” 元素比較普遍,數(shù)據(jù)庫特定的鏈接機(jī)制較為少見。 原生 XML 數(shù)據(jù)庫的引用完整性可分為兩大類:內(nèi)部指針(同一文件內(nèi)的指針)的完整性和外部指針(不同文件之間的指針)的完整性。使用非標(biāo)準(zhǔn)機(jī)制實(shí)現(xiàn)的內(nèi)部指針的引用完整性一向難以達(dá)到,因?yàn)樵?nbsp;XML 數(shù)據(jù)庫無法識(shí)別此類指針。以標(biāo)準(zhǔn)機(jī)制比如 ID/IDREF 或 key/keyref 實(shí)現(xiàn)的內(nèi)部引用完整性至少可通過驗(yàn)證獲得部分支持。 之所以說部分支持,是因?yàn)榇蠖鄶?shù)原生 XML 數(shù)據(jù)庫僅在將文件存入數(shù)據(jù)庫時(shí)才進(jìn)行驗(yàn)證。這樣,如果更新發(fā)生在文件級(jí) - 即刪除和替換文件,驗(yàn)證已足以確保內(nèi)部指針的完整性。但是如果更新發(fā)生在節(jié)點(diǎn)一級(jí) -即插入、修改和刪除節(jié)點(diǎn),則數(shù)據(jù)庫必須執(zhí)行額外的工作(比如校驗(yàn)所有的變化)來確保內(nèi)部指針的引用完整性。支持該功能的原生 XML 數(shù)據(jù)庫極少(如果有的話)。 對(duì)外部指針的引用完整性(據(jù)我所知)仍未有支持,甚至支持外部指針的數(shù)據(jù)庫都很罕見。假如某個(gè)外部指針指向了數(shù)據(jù)庫中的其他資源,沒有理由不保證其完整性,但如果指向了數(shù)據(jù)庫之外的資源,這種保證的缺乏尚有情可原。例如,某個(gè)文件內(nèi)的一個(gè) XLink 指向了外部網(wǎng)站的某個(gè)文件,數(shù)據(jù)庫顯然無法知道后者是否存在,因而也就無法保證該 XLink 的完整性。 將來,許多原生XML數(shù)據(jù)庫大致都會(huì)以標(biāo)準(zhǔn)的機(jī)制支持內(nèi)部指針的引用完整性。許多原生 XML數(shù)據(jù)庫大約都會(huì)在某種程度上支持外部指針,以及支持指向同一個(gè)數(shù)據(jù)庫中的資源的外部指針的引用完整性。而在目前,多數(shù)情況下還有賴于應(yīng)用程序保證(內(nèi)部或外部)指針的完整性。 6.3.4.3 可伸縮性 (Scalability) 與層次型和關(guān)系型數(shù)據(jù)庫類似,原生XML數(shù)據(jù)庫也使用索引來查找數(shù)據(jù)。這就意味著文件(或文件片斷)的查找只與索引的大小有關(guān),而與文件的大小和數(shù)量無關(guān),因而原生XML數(shù)據(jù)庫定位文件開始的速度和其他使用同一種索引技術(shù)的數(shù)據(jù)庫一樣。由此看來,原生XML數(shù)據(jù)庫的可伸縮性和其他數(shù)據(jù)庫一樣。 與層次型數(shù)據(jù)庫相同而與關(guān)系型數(shù)據(jù)庫不同的是,許多原生XML數(shù)據(jù)庫用物理方法鏈接相關(guān)數(shù)據(jù)。特別是基于文本的原生XML數(shù)據(jù)庫用物理的方法對(duì)相關(guān)數(shù)據(jù)分組,使用專用存儲(chǔ)格式的基于模型的原生XML數(shù)據(jù)庫通常使用物理指針來對(duì)相關(guān)數(shù)據(jù)分組。(建立在關(guān)系數(shù)據(jù)庫之上基于模型的原生XML數(shù)據(jù)庫使用的是邏輯鏈接。) 由于物理鏈接比邏輯鏈接速度快,原生XML數(shù)據(jù)庫和層次型數(shù)據(jù)庫一樣,數(shù)據(jù)的讀出速度比關(guān)系型數(shù)據(jù)庫快得多。因此,從數(shù)據(jù)的讀取方面來看,它應(yīng)具有同樣的可伸縮性。事實(shí)上,在數(shù)據(jù)的讀取能力上XML數(shù)據(jù)庫比關(guān)系型數(shù)據(jù)庫甚至更好,因?yàn)榭缮炜s性與初次索引查找有關(guān),而不是關(guān)系型數(shù)據(jù)庫所用的多次查找。(需要指出,關(guān)系型數(shù)據(jù)庫也以集簇索引(clustered indexes)的形式提供數(shù)據(jù)的物理鏈接。不過,這種鏈接是應(yīng)用于各個(gè)表格而不是整體層次上的。) 令人遺憾的是這種可伸縮性是有限的。就像層次型數(shù)據(jù)庫,原生XML數(shù)據(jù)庫中所用的物理連接只能作用于特定的層次。也就是說,如果數(shù)據(jù)的讀取和數(shù)據(jù)的存儲(chǔ)在同一層次下,則讀取速度很快,否則就不一定快。例如將客戶信息存儲(chǔ)在各個(gè)銷售訂單文件中,則讀取銷售訂單時(shí)的速度很快,而如果需要的數(shù)據(jù)視圖不同,比如要找出某個(gè)客戶的所有訂單將會(huì)很慢,因?yàn)榇藭r(shí)物理連接已不再適用。) 為了緩解這個(gè)問題,原生XML數(shù)據(jù)庫大量使用了索引,經(jīng)常對(duì)所有元素和屬性都作了索引。這雖然有助于減少讀取時(shí)間,卻增加了更新時(shí)間,因?yàn)榫S護(hù)這種索引的代價(jià)很高。在只讀的環(huán)境下這無關(guān)緊要,在交易頻繁的環(huán)境下可能造成麻煩。 最后,對(duì)于未索引數(shù)據(jù)的查找來說,原生XML數(shù)據(jù)庫的可伸縮性比關(guān)系型數(shù)據(jù)庫差的多。此時(shí)這兩種數(shù)據(jù)庫都要線性地查找數(shù)據(jù),而原生XML數(shù)據(jù)庫的情況更為糟糕,因?yàn)樗臄?shù)據(jù)不是完全規(guī)范的。比如你要查找某個(gè)日期的所有銷售訂單,而日期是未經(jīng)索引的。如果用的是關(guān)系型數(shù)據(jù)庫,就要讀取所有OrderDate字段的值,而對(duì)于原生XML數(shù)據(jù)庫,這意味著要讀取每個(gè)銷售訂單文件,并從中查找<OrderDate>元素。不但需要讀取<OrderDate>元素的內(nèi)容;而且還要讀取所有其它文件的內(nèi)容。對(duì)于基于文本的原生XML數(shù)據(jù)庫,情況也很不妙:在與目標(biāo)日期比較之前,必須先對(duì)文本進(jìn)行解析并轉(zhuǎn)換為日期格式。 那么對(duì)你來說,可伸縮性是否嚴(yán)重?這完全取決于你的應(yīng)用。如果你的應(yīng)用程序中所需的數(shù)據(jù)一般都和其存儲(chǔ)形式相同,則原生XML數(shù)據(jù)庫的可伸縮性應(yīng)是不錯(cuò)的。許多以文本為中心的應(yīng)用就屬于這種情形。例如組成產(chǎn)品手冊(cè)的文檔幾乎總是作為整體讀取的。反之,如果你的應(yīng)用中數(shù)據(jù)視圖不是很確定,則可伸縮性有可能出問題。 對(duì)于原生XML數(shù)據(jù)庫的討論就到此結(jié)束。在接下來的兩部分中,我們將考察兩種特殊的原生XML數(shù)據(jù)庫:可持久化DOM和內(nèi)容管理系統(tǒng)。 6.3 可持久化DOM (Persistent DOMs, PDOMs) 由于PDOM樹是實(shí)時(shí)的,數(shù)據(jù)庫通常是在本地。這就是說,它和應(yīng)用程序在同一個(gè)進(jìn)程空間,或者至少在同一部機(jī)器(盡管這并不是必需的)。這是出于性能上的考慮,因?yàn)橥獠繑?shù)據(jù)庫上的PDOM必須經(jīng)常向遠(yuǎn)程服務(wù)器發(fā)出請(qǐng)求。 PDOM在DOM應(yīng)用程序中所起的作用和在面向?qū)ο蟮膽?yīng)用程序中面向?qū)ο蟮臄?shù)據(jù)庫的作用一樣:它為應(yīng)用程序的數(shù)據(jù)提供了可持久化的存儲(chǔ),也可作為應(yīng)用程序的虛擬內(nèi)存。后一種作用對(duì)于操作大型文件的DOM應(yīng)用來說有著特殊的重要性,因?yàn)镈OM與XML文件長度之比很容易超過10。(實(shí)際的系數(shù)取決于文件中文本的平均長度,文本的平均長度較小的文件其系數(shù)較高。) 6.4 內(nèi)容管理系統(tǒng) (Content Management Systems) 版本和訪問控制。 7.0 XML 數(shù)據(jù)庫產(chǎn)品 (Database Products) 8.0 相關(guān)鏈接 (Additional Links) 9.0 意見和反饋 (Comments and Feedback) 感謝Michael Champion, John Cowan, Marc Cyrenne, Marc de Graauw, Kelvin Ginn, Ingo Macherius, Lars Martin, Nick Leaton, Evan Lenz, Michael Rys, Walter Perry, Kimbro Staken, Jim Tivy, Phillipe Vauclair, Dylan Walsh, Irsan Widarto, Morten Primdahl 及其他人的意見和耐心。 |
|
|