DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> Sql server 2005的XML最佳實施策略(2)
Sql server 2005的XML最佳實施策略(2)
編輯:XML詳解     
語句在表 T 的 XML 列 xCol 上創建了名為 idx_xCol 的 XML 索引:

CREATE PRIMARY XML INDEX idx_xCol on T (xCol)

輔助 XML 索引

在創建主 XML 索引之後,您可能希望創建輔助 XML 索引來提高工作負荷中的不同種類查詢的速度。三種類型的輔助 XML 索引 - PATH、PROPERTY 和 VALUE 分別為基於路徑的查詢、自定義屬性管理場合和基於值的查詢提供幫助。PATH 索引在列中的所有 XML 實例上,按照文檔順序生成各個 XML 節點的 (path, value) 對的 B+ 樹。PROPERTY 索引創建各個 XML 實例中 (PK, path, value) 對的聚集 B+ 樹,其中 PK 是基表的主鍵。最後,VALUE 索引在 XML 列中的所有 XML 實例中,按照文檔順序創建各個節點的 (value, path) 對的 B+ 樹。

以下是創建上述一個或多個索引的一些准則:

• 如果工作負荷大量使用 XML 列中的路徑表達式,則 PATH 輔助 XML 索引可能會加快工作負荷的處理速度。最常見的例子是在 T-SQL 的 WHERE 子句中對 XML 列使用 exist() 方法。

• 如果您的工作負荷從單獨的使用路徑表達式的 XML 實例中檢索多個值,則將各個 XML 實例中的路徑聚集到 PROPERTY 索引中可能會很有用。這種情況通常出現在屬性包場合中,此時對象的屬性被獲取並且其主鍵值已知。

• 如果您的工作負荷涉及到查詢 XML 實例中的值,而不知道包含這些值的元素或屬性名稱,則您可能需要創建 VALUE 索引。這通常發生在子代軸查找中,例如 //author[last-name="Howard"],其中 元素可以出現在層次結構的任意級別上。這種情況還會發生在"通配符"查詢中,例如 /book [@* = "novel"],其中查詢將查找具有某個值為 "novel" 的屬性的 元素。

示例:基於路徑的查找

假設下面的查詢在您的工作負荷中很常見:

SELECT pk, xCol

FROM T

WHERE xCol.exist ('/book[@genre = "novel"]') = 1

路徑表達式 /book/@genre 和值 "novel" 對應於 PATH 索引的鍵字段。因此,PATH 類型的輔助 XML 索引對於該工作負荷很有用:

CREATE XML INDEX idx_xCol_Path on T (xCol)

USING XML INDEX idx_xCol FOR PATH

示例:獲取對象的屬性

請考慮下面的查詢,它從表 T 的各個行中檢索一本書的屬性"genre"、"title"和 ISBN:

SELECT xCol.value ('(/book/@genre)[1]', 'varchar(50)'),

xCol.value ('(/book/title)[1]', 'varchar(50)'),

xCol.value ('(/book/@ISBN)[1]', 'varchar(50)')

FROM T

在這種情況下,屬性索引很有用,其創建方式如下所示:

CREATE XML INDEX idx_xCol_Property on T (xCol)

USING XML INDEX idx_xCol FOR PROPERTY

示例:基於值的查詢

在以下查詢中,子代軸或自身軸 (//) 指定了部分路徑,以便基於 ISBN 值的查找可以因為使用 VALUE 索引而受益:

SELECT xCol

FROM T

WHERE xCol.exist ('//book[@ISBN = "1-8610-0157-6"]') = 1

VALUE 索引按如下方式創建:

CREATE XML INDEX idx_xCol_Value on T (xCol)

USING XML INDEX idx_xCol FOR VALUE

XML 列上的全文索引

您可以在 XML 列上創建全文索引,從而將 XML 值的內容編入索引,而忽略 XML 標記。屬性值沒有被編入全文索引(因為它們被視為標記的一部分),並且元素標記被用作標記邊界。在某些情況下,可以將全文搜索與 XML 索引用法結合起來:

• 首先,使用 SQL 全文搜索篩選感興趣的 XML 值。

• 接下來,查詢這些 XML 值,這會使用 XML 列上的 XML 索引。

示例:將全文搜索與 XML 查詢結合起來

在 XML 列上創建全文索引之後,以下查詢將檢查 XML 值是否在書名中包含單詞"custom":

SELECT *

FROM T

WHERE CONTAINS(xCol,'custom')

AND xCol.exist('/book/title/text()[contains(.,"custom")]') =1

CONTAINS() 方法使用全文索引,將文檔中任何地方包含單詞"custom"的 XML 值組合為一個子集。exist() 子句確保單詞"custom"出現在書名中。

使用 CONTAINS() 和 XQuery contains() 的全文搜索具有不同的語義。後者是子字符串匹配,而前者則是使用單詞衍生的標記匹配。因此,如果要搜索標題中的字符串 "run",則 "run"、"runs" 和 "running" 都將匹配,因為全文 CONTAINS() 和 Xquery contains() 都滿足。然而,上述查詢不匹配標題中的單詞"customizable"。(全文 CONTAINS() 失敗,而 Xquery contains() 被滿足)。通常,對於純粹的子字符串匹配,應該刪除全文 CONTAINS() 子句。

而且,全文搜索采用單詞衍生,而 XQuery contains() 是一種字面匹配。這一區別將在下一個示例中闡述。

示例:使用單詞衍生對 XML 值進行全文搜索

通常情況下,不能排除示例:將全文搜索與 XML 查詢結合起來中的 XQuery contains() 檢查。請考慮查詢:

SELECT *

FROM T

WHERE CONTAINS(xCol,'run')

因為使用單詞衍生,所以文檔中的單詞"ran"匹配搜索條件。而且,使用 XQuery 時不會檢查搜索上下文。

在使用被全文索引的 AXSD 將 XML 分解到關系列中時,XML 視圖上的 XPath 查詢不會對基礎表執行全文搜索。

屬性提升

如果主要是對少量元素和屬性值進行查詢(例如,基於客戶 ID 查找客戶,即指定了 /Customer/@CustId 的值),您可能希望將這些數量提升到關系列中。當檢索了整個 XML 實例,但只對一小部分 XML 數據進行查詢時,這將很有用。在 XML 列上創建 XML 索引是沒有必要的;相反,可以將被提升的列編入索引。必須編寫查詢以使用提升的列(即,查詢優化器不會將對 XML 列的查詢重新定向到提升的列)。

提升的列可以是同一表中的計算列,也可以是表中單獨的、用戶維護的列。當從各個 XML 實例中提升唯一值(即單值屬性)時,這已足夠。然而,對於多值屬性,您必須為該屬性創建單獨的表,如下所述。

基於 XML 數據類型的計算列

可以使用能夠激活 XML 數據類型方法的用戶定義函數 (UDF) 來創建計算列。計算列的類型可以是任何 SQL 類型,包括 XML。以下示例說明了這一點。

示例:基於 XML 數據類型方法的計算列

為書籍的 ISBN 創建用戶定義的函數:

CREATE FUNCTION udf_get_book_ISBN (@xData XML)

RETURNS varchar(20)

BEGIN

DECLARE @ISBN varchar(20)

SELECT @ISBN = @xData.value('/book[1]/@ISBN', 'varchar(20)')

RETURN @ISBN

END

為 ISBN 向表中添加一個計算列:

ALTER TABLE T

ADD ISBN AS dbo.udf_get_book_ISBN(xCol)

可以用通常的方式將計算列編入索引。

示例:基於 XML 數據類型方法的計算列上的查詢

要獲取其 ISBN 為 0-7356-1588-2 的 ,可以改寫 XML 列上的查詢

SELECT xCol

FROM T

WHERE xCol.exist ('/book[@ISBN = "0-7356-1588-2"]') = 1

以使用計算列,如下所示:

SELECT xCol

FROM T

WHERE ISBN = '0-7356-1588-2'

可以創建一個用戶定義的函數,返回 XML 數據類型和使用該 UDF 的計算列。然而,無法在計算的 XML 列上創建 XML 索引。

創建屬性表

您可能希望將 XML 數據中的某些多值屬性提升到一個或多個表中,在這些表上創建索引,並且重定向查詢以使用這些表。典型的情形是一小部分屬性覆蓋了大部分查詢工作負荷。您可以執行以下操作:

• 創建一個或多個表以存放多值屬性。您可能發現采用以下處理方式會很方便:每個表存儲一個屬性,並且在屬性表中復制基表的主鍵以便與基表進行向後聯接。

• 如果您希望保持屬性的相對順序,則需要為相對順序引入一個單獨的列。

• 在 XML 列上創建觸發器以便維護屬性表。在觸發器中,執行以下操作:

• 使用 XML 數據類型方法(如 nodes() 和 value())在屬性表中插入和刪除行。(有關 nodes() 方法的詳細信息,請參閱 Value()、Nodes() 和 OpenXML()。)

• 在 CLR 中創建流式表值函數,以便在屬性表中插入和刪除行。

• 編寫查詢,以便對屬性表進行 SQL 訪問,以及對基表中的 XML 列進行 XML 訪問,這需要使用這些表的主鍵將其相互聯接。

示例:創建屬性表

假設您希望提升作者的名字。書籍有一個或多個作者,因此名字是一個多值屬性。每個名字都存儲在屬性表的單獨行中。在屬性表中復制了基表的主鍵以便向後聯接。

create table tblPropAuthor (propPK int, propAuthor varchar(max))

示例:創建用戶定義的函數以便從 XML 實例生成行集

下面的表值函數 udf_XML2Table 接受一個主鍵值和一個 XML 實例。它將檢索 元素的所有作者的名字,並返回(主鍵,名字)對行集。

create function udf_XML2Table (@pk int, @xCol XML)

returns @ret_Table table (propPK int, propAuthor varchar(max))

with schemabinding

as

begin

insert into @ret_Table

select @pk, nref.value('.', 'varchar(max)')

from @xCol.nodes('/book/author/first-name') R(nref)

return

end

示例:創建觸發器以填充屬性表

插入觸發器:在屬性表中插入行

create trigger trg_docs_INS on T for insert

as

declare @wantedXML XML

declare @FK int

select @wantedXML = xCol from inserted

select @FK = PK from inserted

insert into tblPropAuthor

select * from dbo.udf_XML2Table(@FK, @wantedXML)

刪除觸發器:基於刪除行的主鍵值,從屬性表中刪除行

create trigger trg_docs_DEL on T for delete

as

declare @FK int

select @FK = PK from deleted

delete tblPropAuthor where propPK = @FK

更新觸發器:在與更新的 XML 實例對應的屬性表中刪除現有行,並且在該屬性表中插入新行

create trigger trg_docs_UPD

on T

for update

as

if update(xCol) or update(pk)

begin

declare @FK int

declare @wantedXML XML

select @FK = PK from deleted

delete tblPropAuthor where propPK = @FK

select @wantedXML = xCol from inserted

select @FK = pk from inserted

insert into tblPropAuthor

select * from dbo.udf_XML2Table(@FK, @wantedXML)

end

示例:查找作者的名字為"David"的 XML 實例

可以在 XML 列上表示該查詢。另外,還可以在屬性表中搜索名字"David",然後與基表執行向後聯接以返回 XML 實例,如下所示:

SELECT xCol

FROM T JOIN tblPropAuthor ON T.pk = tblPropAuthor.propPK

WHERE tblPropAuthor.propAuthor = 'David'

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved