Microsoft SQL Server 2005 為 XML 數據處理提供了廣泛的支持。XML 值可以自然地存儲在 XML 數據類型列中,而後者可以根據 XML 架構集合進行類型化,或者保持非類型化。可以將 XML 列編入索引。而且,使用 XQuery 和 XML DML(為進行數據修改而進行的擴展)可以支持細粒度的數據操作。
SQL Server 2000 和 SQLXML Web Release 提供了強大的 XML 數據管理功能。這些功能致力於關系數據和 XML 數據之間的映射。可以使用帶有批注的 XSD (AXSD) 來定義關系數據的 XML 視圖,以便提供以 XML 為中心的方法,該方法支持 XML 數據的批量數據加載、查詢和更新功能。Transact-SQL 擴展提供了以 SQL 為中心的方法,以便將關系查詢結果映射到 XML(使用 FOR XML),以及從 XML 生成關系視圖(使用 OpenXML)。這些支持已在 SQL Server 2005 中得到了擴展。結合新增的原生 XML 支持,SQL Server 2005 提供了一種強大的平台,以便針對半結構化和非結構化的數據管理開發功能豐富的應用程序。
本文提供了 SQL Server 2005 中的 XML 數據建模和使用准則。它包含以下兩個主題:
• 數據建模
XML 數據可用多種方式存儲在 SQL Server 2005 中,例如,使用原生 XML 數據類型和分散到表中的 XML。本主題提供了做出適當的選擇以便對 XML 數據進行建模的准則。同時,還討論了將 XML 數據編入索引、屬性提升和 XML 實例的類型化。
• 用法
本主題討論了與用法相關的主題(如將 XML 數據加載到服務器以及查詢編譯中的類型推理),解釋和區分了密切相關的功能,並推薦了這些功能的適當使用。文中通過示例闡述了各種概念。
為了最大限度地領會本文的內容,您應該對 SQL Server 環境中的 XML 功能有一個基本的了解。請參閱 XML Support in Microsoft SQL Server 2005。
返回頁首
數據建模
本節概述了使用 SQL Server 2005 中的 XML 的理由,提供了在原生 XML 存儲和 XML 視圖技術之間進行選擇的准則,並且提供了數據建模建議。
關系或 XML 數據模型
如果您的數據是高度結構化的,具有已知的架構,則關系模型可能對於數據存儲最為有效。Microsoft SQL Server 提供了您可能需要的必要功能和工具。另一方面,如果結構是靈活的(半結構化和非結構化)或未知的,則必須適當地考慮如何對此類數據進行建模。
如果您需要獨立於平台的模型,以便確保使用結構化和語義標記的數據的可移植性,則 XML 是一種不錯的選擇。而且,如果滿足下列某些屬性,則它還是一種適當的選擇:
• 您的數據比較稀疏,或者您不了解數據的結構,或者數據的結構將來可能發生重大更改。
• 您的數據表示容器層次結構(與實體中的引用相對),並且可能是遞歸的。
• 您的數據具有內在的順序。
• 您希望對數據進行查詢,或者基於其結構更新部分數據。
如果上述任一條件都不滿足,則您應該使用關系數據模型。例如,如果您的數據是 XML 格式,但您的應用程序很少使用數據庫來存儲和檢索數據,則 [n]varchar(max) 列就能滿足您的全部需要。在 XML 列中存儲數據可以帶來其他好處 - 引擎將檢查數據格式規范或者有效,並且支持對 XML 數據進行細粒度的查詢和更新。
在 SQL Server 2005 中存儲 XML 數據的理由
以下為一些使用 SQL Server 2005 中的原生 XML 功能而不是在文件系統中管理 XML 數據的理由:
• 您希望使用數據庫服務器的管理功能來管理 XML 數據(例如,備份、恢復和復制)。
• 您希望以高效的方式和事務處理方式來共享、查詢和修改 XML數據。細粒度的數據訪問對於您的應用程序而言很重要。例如,您可能需要提取 XML 文檔內部的某些節,或者您可能需要插入一個新節而不是替換整個文檔。
• 您具有關系數據和 SQL 應用程序,您希望在應用程序內部的關系數據和 XML 數據之間進行互操作。對於跨域應用程序,您需要有關查詢和數據修改的語言支持。
• 您希望服務器能夠保證數據格式規范,並能夠視情況根據 XML 架構來驗證數據。
• 您需要將 XML 數據編入索引以便實現高效的查詢處理和良好的可伸縮性,並且使用一流的查詢優化器。
• 您希望對 XML 數據進行 SOAP、ADO.Net 和 OLE DB 訪問。
如果不滿足上述任一條件,您最好將數據存儲為非 XML 的大型數據類型,如 [n]varchar(max) 或 varbinary(max)。
XML 存儲選項
SQL Server 2005 中的 XML 的存儲選項如下所示:
• 本機存儲采用 XML 數據類型:
用能夠保留數據的 XML 內容(如容器層次結構、文檔順序、元素和屬性值等等)的內部表示形式存儲數據。具體說來,就是保留 XML 數據的信息集內容(有關信息集的詳細信息,請參閱 http://www.w3.org/TR/xml-infoset)。它可能不是文本 XML 的精確副本,因為未保留以下信息:無關緊要的空格、屬性順序、命名空間前綴和 XML 聲明。
對於類型化的 XML 數據類型(即綁定到 XML 架構的 XML 數據類型)而言,負責向信息集添加類型信息的後架構驗證信息集 (Post Schema Validation Infoset, PSVI) 以內部表示形式編碼。這會顯著提高分析速度。(有關詳細信息,請參閱 W3C XML 架構規范,網址為 http://www.w3.org/TR/xmlschema-1 和 http://www.w3.org/TR/XMLschema-2。)
• XML 和關系存儲之間的映射:
使用帶有批注的架構 (AXSD),XML 將被分解到一個或多個表中的列,並且在關系級別保留數據的保真度 - 保留層次結構,但忽略元素順序。架構不能是遞歸的。
• 大型對象存儲([n]varchar(max) 和 varbinary(max)):
存儲了數據的精確副本。這對於特殊用途的應用(如法律文檔)很有用。大多數應用不要求精確副本,XML 內容(信息集保真度)即可滿足需要。
通常情況下,可能需要組合使用這些方法。例如,您可能需要用 XML 數據類型列存儲 XML 數據,並將其中的屬性提升到關系列中。相反,您可能希望使用映射技術,將非遞歸部分存儲到非 XML 列中,而僅將遞歸部分存儲到 XML 數據類型列中。
XML 技術的選擇
XML 技術(原生 XML 與 XML 視圖)的選擇通常取決於下列因素:
• 存儲選項:
您的 XML 數據可能更適合於大型對象存儲(例如,產品手冊),或者更適合於存儲在關系列中(例如,轉換到 XML 的行項目)。每個存儲選項都在不同程度上保留了文檔保真度。
• 查詢功能:
基於查詢的性質以及對 XML 數據進行查詢的程度,您可能發現一個存儲選項比其他存儲選項更為適合。細粒度的 XML 數據查詢(例如,XML 節點上的謂詞計算)在這兩個存儲選項中受到不同程度的支持。
• 將 XML 數據編入索引:
您可能希望將 XML 數據編入索引,以便提高 XML 查詢性能。索引選項隨存儲選項的不同而不同;您需要進行適當的選擇以優化工作量。
• 數據修改功能:
某些工作量涉及到對 XML 數據進行細粒度的修改(例如,在文檔內添加新節),而其他工作量則不涉及(例如,Web 內容)。對於您的應用程序而言,數據修改語言支持可能很重要。
• 架構支持:
您的 XML 數據可能通過架構進行描述,這可能是也可能不是 XML 架構文檔。對架構綁定 XML 的支持取決於 XML 技術。
不用說,不同的選擇具有不同的性能特性。
原生 XML 存儲
可以將您的 XML 數據存儲在服務器的 XML 數據類型列中。在下列情況下,這將是一個適當的選擇:
• 您需要一種在服務器上存儲 XML 數據的簡單方法,同時需要保留文檔順序和文檔結構。
• 您的 XML 數據可能有也可能沒有架構。
• 您需要查詢和修改您的 XML 數據。
• 您需要將 XML 數據編入索引以便實現更為快速的查詢處理。
• 您的應用程序需要系統目錄視圖以管理您的 XML 數據和 XML 架構。
當您的 XML 文檔具有多種結構時,或者當您的 XML 文檔符合不同的或復雜的架構,而這些架構很難映射到關系結構時,原生 XML 存儲將很有用。
示例:使用 XML 數據類型對 XML 數據進行建模
考慮一個 XML 格式的產品手冊,其中每個主題對應單獨的一章,而每章內又有多節。一節可以包含多個子節,因此 是一個遞歸元素。產品手冊包含大量混合內容、圖表和技術資料;數據是半結構化的。用戶可能希望對感興趣的主題執行與上下文有關的搜索(例如,在有關"索引"的章內部搜索有關"聚集索引"的節),並且查詢技術數量。
XML 文檔的合適存儲模型是 XML 數據類型列。這可以保留 XML 數據的信息集內容。將 XML 列編入索引可以提高查詢性能。
示例:保留 XML 數據的精確副本
假設政府法令要求您保留 XML 文檔(例如,已簽署的文檔、法律文檔或股票交易訂單)的精確文本副本。您可能需要將您的文檔存儲在 [n]varchar(max) 列中。
對於查詢,可在運行時將數據轉換為 XML 數據類型,然後對其執行 Xquery。運行時轉換可能代價高昂,尤其是在文檔很大時。如果您經常進行查詢,可以采用冗余方式將文檔存儲在 XML 數據類型列中並將其編入索引,同時從 [n]varchar(max) 列返回精確的文檔副本。
XML 列可能是基於 [n]varchar(max) 列的計算列。您不能在 XML 計算列上創建 XML 索引,也不能在 [n]varchar(max) 或 varbinary(max) 列上生成 XML 索引。
XML 視圖技術
通過在 XML 架構和數據庫的表之間定義映射,可以創建持久性數據的"XML 視圖"。可以使用 XML 批量負載來填充使用 XML 視圖的基礎表。您可以查詢使用 XPath 1.0 的 XML 視圖;該查詢將被轉換為針對表的 SQL 查詢。與此類似,更新也會被傳遞到這些表。
在以下情況下,此技術很有用:
• 您希望擁有以 XML 為中心的編程模型,該模型使用現有關系數據上的 XML 視圖。
• 您的 XML 數據具有架構 (XSD, XDR),它可能由外部合作伙伴提供。
• 數據的順序不重要,或者您的可查詢數據不是遞歸的,或者預先已經知道最大遞歸深度。
• 您希望通過使用 XPath 1.0 的 XML 視圖來查詢和修改數據。
• 您希望批量加載 XML 數據,並將其分解到使用 XML 視圖的基礎表中。
這方面的例子包括以 XML 形式公開以便用於數據交換和 Web 服務的關系數據,以及具有固定架構的 XML 數據。有關詳細信息,請參閱 SQLXML 開發人員中心。
示例:使用帶有批注的 XML 架構 (AXSD) 對數據進行建模
假設您現有一些希望以 XML 形式進行操作的關系數據(例如,客戶、訂單和行項目)。請使用 AXSD 在關系數據上定義 XML 視圖。通過 XML 視圖,可以將 XML 數據批量加載到表中,以及使用 XML 視圖查詢和更新關系數據。如果您需要在自己的 SQL 應用程序持續工作時與其他應用程序中的 XML 標記交換數據,則該模式很有用。
混合模型
很多時候,適合將關系數據和 XML 數據類型列結合起來進行數據建模。可以將 XML 數據中的某些值存儲在關系列中,而將其余或全部 XML 值存儲在 XML 列中。這可能會產生更好的性能(例如,可以完全控制在關系列上創建的索引)和鎖定特性。然而,這需要您承擔更多的責任來管理數據存儲。
要存儲在關系列中的值取決於您的工作負荷。例如,如果您基於路徑表達式 /Customer/@CustId 檢索全部 XML 值,則通過將 CustId 屬性的值提升到關系列中以及將其編入索引,可能產生更高的查詢性能。另一方面,如果您的 XML 數據被廣泛且非冗余地分解到關系列中,則重新組合的成本可能很大。
對於高度結構化的 XML 數據(例如,表的內容已經轉換到 XML),可以將所有值映射到關系列(可能使用 XML 視圖技術)。
返回頁首
使用 XML 數據類型進行數據建模
本節討論有關原生 XML 存儲的數據建模主題。這些主題包括將 XML 數據編入索引、屬性提升和類型化 XML 數據類型。
相同或不同的表
XML 數據類型列可以在包含其他關系列的表中創建,也可以在與主表之間具有外鍵關系的獨立表中創建。
在滿足下列某個條件時,請在同一個表中創建 XML 數據類型列:
• 您的應用程序在 XML 列上執行數據檢索,並且不需要 XML 列上的 XML 索引。 或者
• 您需要在 XML 數據類型列上生成 XML 索引,並且主表的主鍵與其聚集鍵相同。有關詳細信息,請參閱將 XML 數據類型列編入索引一節。
在滿足下列條件時,請在單獨的表中創建 XML 數據類型列:
• 您需要在 XML 數據類型列上生成 XML 索引,但主表的主鍵與其聚集鍵不同,或者主表不具有主鍵,或者主表是一個堆(也就是說,沒有聚集鍵)。如果主表已經存在,則這可能是真的。
• 您不希望表掃描由於表中存在 XML 列(無論它是存儲在行中還是存儲在行外,都會占用空間)而降低速度。
XML 數據的粒度
XML 列中存儲的 XML 數據的粒度對於鎖定和更新特性而言至關重要。SQL Server 對 XML 和非 XML 數據采用了相同的鎖定機制。因此,行級鎖定會導致相應行中的所有 XML 實例被鎖定。當粒度比較大時,鎖定大型 XML 實例以便進行更新會導致多用戶場合下的吞吐量下降。另一方面,嚴重的分解會丟失對象封裝並提高重新組合成本。
對 XML 實例進行更新會將現有實例替換為更新後的實例,即使只修改單個屬性的值。XML 數據粒度越大,更新成本就越高。較小的 XML 實例會產生較高的更新性能。
對於良好的設計而言,重要的是保持數據建模需要與鎖定和更新特性之間的平衡。
非類型化、類型化和受約束的 XML 數據類型
SQL Server 2005 XML 數據類型實現了 ISO SQL-2003 標准 XML 數據類型。因此,它可以在非類型化 XML 列中存儲格式規范的 XML 1.0 文檔以及帶有文本節點和任意數量頂級元素的所謂的 XML 內容片段。系統將檢查數據的格式是否規范,不要求將列綁定到 XML 架構,並且拒絕在擴展意義上格式不規范的數據。對於非類型化 XML 變量和參數,也是如此。
如果您具有描述 XML 數據的 XML 架構,則可以將這些架構與 XML 列相關聯,以便產生類型化 XML。XML 架構用於對數據進行有效性驗證,在查詢和數據修改語句編譯過程中執行比非類型化 XML 更准確的類型檢查,以及優化存儲和查詢處理。
在下列條件下,請使用非類型化 XML 數據類型:
• 您沒有對應於 XML 數據的架構
• 您擁有架構,但不希望服務器對數據進行有效性驗證。當應用程序在服務器中存儲數據之前執行客戶端驗證時,或者暫時存儲根據架構無效的 XML 數據時,或者使用在服務器中不受支持的架構組件(例如 key/keyref)時,有時會出現這種情況。
在下列條件下,請使用類型化 XML 數據類型:
• 您擁有對應於 XML 數據的架構,並且希望服務器按照 XML 架構對 XML 數據進行有效性驗證。
• 您希望充分利用基於類型信息的存儲和查詢優化。
• 您希望在查詢的編譯過程中更充分地利用類型信息。
類型化 XML 列、參數和變量可以存儲 XML 文檔或內容 - 您在聲明時必須將它們指定為標志(分別指定為 DOCUMENT 或 CONTENT)。而且,您必須提供 XML 架構集合。如果每個 XML 實例恰好有一個頂級元素,請指定 DOCUMENT;否則,請使用 CONTENT。查詢編譯器在查詢編譯過程的類型檢查中使用 DOCUMENT 標記來推理唯一的頂級元素。
除了將 XML 列類型化以外,您還可以在類型化或非類型化 XML 數據類型列上使用關系(列或行)約束。在下列條件下,請使用約束:
• 無法在 XML 架構中表示業務規則。例如,花店的送貨地址必須在其營業地點周圍 50 英裡范圍之內,這可以編寫為 XML 列上的約束。該約束可能涉及到 XML 數據類型方法。
• 您的約束涉及到表中的其他 XML 列或非 XML 列。這方面的一個例子是:強制 XML 實例中存在的 Customer ID (/Customer/@CustId) 與關系 CustomerID 列中的值匹配。
文檔類型定義 (DTD)
XML 數據類型列、變量和參數可以使用 XML 架構而不是 DTD 加以類型化。然而,對於非類型化和類型化 XML,都可以使用內聯 DTD 來提供默認值,以便將實體引用替換為它們的擴展形式。
您可以使用第三方工具將 DTD 轉化為 XML 架構文檔,並且將 XML 架構加載到數據庫中。
將 XML 數據類型列編入索引
可以在 XML 數據類型列上創建 XML 索引。這會將該列中 XML 實例上的所有標記、值和路徑編入索引,從而提高查詢性能。在下列條件下,您的應用程序可能受益於 XML 索引:
• 對 XML 列進行查詢在您的工作負荷中很常見。必須考慮數據修改過程中的 XML 索引維護成本。
• XML 值相對較大,而檢索的部分相對較小。生成索引可以避免在運行時分析全部數據,並且因為受益於索引查找而提高查詢處理的性能。
XML 列上的第一個索引是"主 XML 索引"。通過該索引,可以在 XML 列上創建三種類型的輔助 XML 索引,從而提高常見種類的查詢的速度,如下節所述。
主 XML 索引
這會將 XML 列中的 XML 實例內部的所有標記、值和路徑編入索引。基表(即包含 XML 列的表)必須在該表的主鍵上具有聚集索引;主鍵用於將索引行與基表中的行相關聯。從 XML 列中檢索完整的 XML 實例(例如 SELECT *)。查詢使用主 XML 索引,並返回標量值或使用索引本身的 XML 子樹。
示例:創建主 XML 索引
在我們的多數示例中,都使用帶有非類型化 XML 列的表 T (pk INT PRIMARY KEY, xCol XML),這些示例都可以簡單地擴展為類型化 XML 的形式(有關使用類型化 XML 的信息,請參閱 SQL Server 2005 聯機圖書)。為了便於說明,將針對如下所示的 XML 數據實例描述查詢: