指定選擇性 XML 索引的路徑和最佳化提示

適用於:SQL ServerAzure SQL DatabaseAzure SQL 受控執行個體Microsoft Fabric 中的 SQL 資料庫

本文說明建立或改變選擇性 XML 索引時,如何指定要編製索引的節點路徑以及索引的最佳化提示。

您會同時在下列其中一個陳述式中指定節點路徑及最佳化提示:

如需選擇性 XML 索引的詳細資訊,請參閱 選擇性 XML 索引 (SXI)。

了解不具類型之 XML 中的 XQuery 和 SQL Server 類型

選擇性 XML 索引支援兩種類型的系統:XQuery 類型和 SQL Server 類型。 索引路徑可用來比對 XQuery 運算式,或是比對 value() 資料類型之 方法的傳回類型。

  • 如果要編製索引的路徑未加上註釋,或是使用 XQUERY 關鍵字註釋,則路徑會比對 XQuery 表達式。 XQUERY 註解的節點路徑有兩種變化:

    • 如果您未指定 XQUERY 關鍵字和 XQuery 資料類型,則會使用預設對應。 通常效能和儲存並非最佳狀態。

    • 如果您指定 XQUERY 關鍵字和 XQuery 資料類型,並且選擇性地指定其他最佳化提示,就可以達到最佳效能和最有效率的儲存。 不過,轉換可能會失敗。

  • 當一個要編製索引的路徑用 SQL 關鍵字註解時,該路徑會匹配 value() 資料類型的 方法的傳回類型。 指定適當的 SQL Server 資料類型,也就是預期從 value() 方法得到的傳回類型。

XQuery 運算式的 XML 類型系統與套用至 value() 方法之 xml 資料類型的 SQL Server 類型系統之間,存在細微的差異。 這些差異包括下列幾項:

  • XQuery 類型系統會考慮尾端空白。 例如,根據 XQuery 類型語意,字串 "abc" 與 "abc " 不相等,但在 SQL Server 中這些字串相等。

  • XQuery 浮點資料類型支援 +/- 零和 +/- 無限大這些特殊值。 SQL Server 浮點資料類型不支援這些特殊值。

不具類型 XML 中的 XQuery 類型

  • XQuery 類型會在 xml 資料類型的所有方法中,比對 XQuery 運算式,包括 value() 方法。

  • XQuery 類型支援以下優化提示:node()、SINGLETON、DATA TYPE和 MAXLENGTH。

對於在不具類型 XML 上的 XQuery 運算式,您可以選擇兩種作業模式:

  • 預設對應模式。 在此模式中,您只會指定建立選擇性 XML 索引時的路徑。

  • 使用者指定的對應模式。 在此模式中,您會指定路徑和選用的最佳化提示。

預設對應模式會使用保守儲存選項,這種選項總是安全且普遍。 它可以比對任何運算式類型。 預設對應模式的限制在於效能未達最佳,因為需要的執行時間轉型次數增加,且次要索引無法使用。

以下範例是使用預設對應建立的選擇性 XML 索引。 針對這三種路徑會使用預設節點類型 (xs:untypedAtomic) 和基數。

CREATE SELECTIVE XML INDEX example_sxi_UX_default
ON Tbl(xmlcol)
FOR
(
    mypath01 =  '/a/b',
    mypath02 = '/a/b/c',
    mypath03 = '/a/b/d'
);

使用者指定的對應模式可讓您指定類型和基數,讓節點獲得更佳的效能。 不過,這種效能提升是藉由降低安全性 (因為轉換可能會失敗) 與普遍性 (因為只有指定的類型會與選擇性 XML 索引比對) 達成。

不具類型 XML 的 XQuery 支持的類型包括:

  • xs:boolean
  • xs:double
  • xs:string
  • xs:date
  • xs:time
  • xs:dateTime

如果未指定類型,則會假設節點為 xs:untypedAtomic 資料類型。

您可以最佳化透過下列方式顯示的選擇性 XML 索引:

CREATE SELECTIVE XML INDEX example_sxi_UX_optimized
ON Tbl(xmlcol)
FOR
(
    mypath= '/a/b' as XQUERY 'node()',
    pathX = '/a/b/c' as XQUERY 'xs:double' SINGLETON,
    pathY = '/a/b/d' as XQUERY 'xs:string' MAXLENGTH(200) SINGLETON
);
-- mypath - Only the node value is needed; storage is saved.
-- pathX - Performance is improved; secondary indexes are possible.
-- pathY - Performance is improved; secondary indexes are possible; storage is saved.

不具類型 XML 中的 SQL Server 類型

  • SQL Server 類型會比對 value() 方法的傳回值。

  • SQL Server 類型支援以下最佳化提示:SINGLETON。

指定類型是對於傳回 SQL Server 類型的路徑所必需的。 請使用您在 value() 方法中所用的相同 SQL Server 類型。

請考慮以下查詢:

SELECT T.record,
    T.xmldata.value('(/a/b/d)[1]', 'NVARCHAR(200)')
FROM myXMLTable T;

指定的查詢會傳回從路徑 /a/b/d 提取後封裝成 NVARCHAR(200) 資料類型的值,因此節點的資料類型顯而易見。 不過,沒有任何結構描述可用來在不具類型的 XML 中指定節點基數。 若要指定節點 d 在其父節點 b下最多出現一次,請建立使用 SINGLETON 最佳化提示的選擇性 XML 索引,如下所示:

CREATE SELECTIVE XML INDEX example_sxi_US
ON Tbl(xmlcol)
FOR
(
    node1223 = '/a/b/d' as SQL NVARCHAR(200) SINGLETON
);

了解類型化 XML 的選擇性 XML 索引支援功能

SQL Server 中的有類型的 XML 是與特定 XML 文件相關聯的模式。 結構描述會定義節點的整體文件結構和類型。 如果結構描述存在,選擇性 XML 索引會在使用者升級路徑時套用結構描述的結構,因此不需要指定路徑的 XQUERY 類型。

選擇性 XML 索引支援下列 XSD 類型:

  • xs:anyUri
  • xs:boolean
  • xs:date
  • xs:dateTime
  • xs:day
  • xs:decimal
  • xs:double
  • xs:float
  • xs:int
  • xs:integer
  • xs:language
  • xs:long
  • xs:name
  • xs:NCName
  • xs:negativeInteger
  • xs:nmtoken
  • xs:nonNegativeInteger
  • xs:nonPositiveInteger
  • xs:positiveInteger
  • xs:qname
  • xs:short
  • xs:string
  • xs:time
  • xs:token
  • xs:unsignedByte
  • xs:unsignedInt
  • xs:unsignedLong
  • xs:unsignedShort

在擁有相關結構描述的文件上建立選擇性 XML 索引時,於建立或修改索引時指定 XQuery 類型會傳回錯誤。 使用者可以在路徑優化部分使用 SQL 類型註解。 SQL 類型必須是來自結構描述中所定義 XSD 類型的有效轉換,否則會擲回錯誤。 所有具有適當 XSD 表示的 SQL 類型都可支援,但不包括日期/時間類型。

注意

如果選擇性 XML 索引路徑升級中指定的類型與 value() 方法傳回值相同,則會使用選擇性索引。

下列最佳化提示可以搭配具類型的 XML 文件使用:

  • node() 最佳化提示。

  • MAXLENGTH 最佳化提示可以搭配 xs:string 類型用來縮短索引值。

如需最佳化提示的詳細資訊,請參閱 指定最佳化提示。

指定路徑

選擇性 XML 索引可讓您僅索引與預期執行之查詢相關的預存 XML 資料中節點的子集。 如果相關節點的子集大幅少於 XML 文件中節點的總數,選擇性 XML 索引只會儲存相關的節點。 若要利用選擇性 XML 索引的優點,請識別要索引的正確節點子集。

選擇要編製索引的節點

您可以利用下列兩種原則,識別要加入至選擇性 XML 索引的正確節點子集。

  1. 原則 1:若要評估特定 XQuery 運算式,請為您需要檢查的所有節點編製索引。

    • 索引在 XQuery 運算式中存在或使用其值的所有節點。

    • 索引 XQuery 運算式中套用 XQuery 述詞的所有節點。

    請思考本文中對範例 XML 文件執行的下列查詢:

    SELECT T.record FROM myXMLTable T
    WHERE T.xmldata.exist('/a/b[./c = "43"]') = 1;
    

    為了傳回滿足此查詢的 XML 執行個體,選擇性 XML 索引需要在每一個 XML 執行個體中檢查兩個節點:

    • 節點 c,因為它的值在 XQuery 運算式中使用。

    • 節點 b,因為在 XQuery 表達式中對節點 b 套用了謂詞。

  2. 原則 2:為了達到最佳效能,請為評估指定 XQuery 運算式所需的所有節點編製索引。 如果您只為部分節點編製索引,則選擇性 XML 索引可改善僅包括索引節點的子運算式評估。

若要改善上面所示 SELECT 陳述式的效能,您可以建立下列選擇性 XML 索引:

CREATE SELECTIVE XML INDEX simple_sxi
ON Tbl(xmlcol)
FOR
(
    path123 =  '/a/b',
    path124 =  '/a/b/c'
);

為相同路徑編製索引

您無法將相同的路徑在路徑名稱不同的情況下宣傳為相同的資料類型。 例如,下列查詢會引發錯誤,因為 pathOne 和 pathTwo 相同:

CREATE SELECTIVE INDEX test_simple_sxi ON T1(xmlCol)
FOR
(
    pathOne = 'book/authors/authorID' AS XQUERY 'xs:string',
    pathTwo = 'book/authors/authorID' AS XQUERY 'xs:string'
);

不過,您可以將相同路徑轉化為具有不同名稱的不同資料類型。 例如,現在可接受下列查詢,因為資料類型不同:

CREATE SELECTIVE INDEX test_simple_sxi ON T1(xmlCol)
FOR
(
    pathOne = 'book/authors/authorID' AS XQUERY 'xs:double',
    pathTwo = 'book/authors/authorID' AS XQUERY 'xs:string'
);

範例

以下提供其他範例,說明如何針對不同 XQuery 類型選取要編製索引的正確節點。

範例 1

以下是使用 exist() 方法的簡單 XQuery:

SELECT T.record FROM myXMLTable T
WHERE T.xmldata.exist('/a/b/c/d/e/h') = 1;

下表顯示應索引的節點,以便讓這個查詢使用選擇性 XML 索引。

要包含在索引中的節點 索引此節點的原因
/a/b/c/d/e/h 會在 h 方法中評估節點 exist() 是否存在。

範例 2

以下是前一個 XQuery 較為複雜的變化,套用了一個述詞:

SELECT T.record FROM myXMLTable T
WHERE T.xmldata.exist('/a/b/c/d/e[./f = "SQL"]') = 1;

下表顯示應索引的節點,以便讓這個查詢使用選擇性 XML 索引。

要包含在索引中的節點 索引此節點的原因
/a/b/c/d/e 述詞被套用在節點 e 上。
/a/b/c/d/e/f 節點 f 的值會在述詞內評估。

範例 3

以下查詢較為複雜,使用了 value() 子句:

SELECT T.record,
    T.xmldata.value('(/a/b/c/d/e[./f = "SQL"]/g)[1]', 'nvarchar(100)')
FROM myXMLTable T;

下表顯示應索引的節點,以便讓這個查詢使用選擇性 XML 索引。

要包含在索引中的節點 索引此節點的原因
/a/b/c/d/e 述詞被套用在節點 e 上。
/a/b/c/d/e/f 節點 f 的值會在述詞內評估。
/a/b/c/d/e/g 節點 g 的值是由 value() 方法傳回。

範例 4

以下是在 exist() 子句內使用 FLWOR 子句的查詢。 (FLWOR 這個名稱來自五個子句,這五個子句構成 XQuery FLWOR 運算式:for、let、where、order by 和 return)。

SELECT T.record FROM myXMLTable T
WHERE T.xmldata.exist('
  For $x in /a/b/c/d/e
  Where $x/f = "SQL"
  Return $x/g
') = 1;

下表顯示應索引的節點,以便讓這個查詢使用選擇性 XML 索引。

要包含在索引中的節點 索引此節點的原因
/a/b/c/d/e FLWOR 子句中會評估節點 e 是否存在。
/a/b/c/d/e/f 節點 f 的值會在 FLWOR 子句中評估。
/a/b/c/d/e/g g 方法會評估節點 exist() 是否存在。

指定最佳化提示

您可以使用選用的最佳化提示,為藉由選擇性 XML 索引所索引的節點指定額外的映射詳細資訊。 例如,您可以指定節點的資料類型和基數,以及有關資料結構的特定資訊。 這項額外資訊可提供更好的映射。 此外還能獲得效能提升和 (或) 節省儲存空間的結果。

最佳化提示是選擇性的用法。 您可以一律接受預設對應,雖然這些對應可靠,但不一定能提供最佳的效能或最佳的儲存空間。

某些最佳化提示 (例如 SINGLETON 提示) 會對資料形成條件約束。 在某些情況下,如果不符合這些條件約束,可能會引發錯誤。

最佳化提示的優點

下表會識別支援更有效率的儲存或提升效能的最佳化提示。

最佳化提示 更有效率的儲存 提升效能
node() 是 否
單身人士 否 是
資料 TYPE 是 是
MAXLENGTH 是 是

最佳化提示和資料類型

您可以將節點索引編製為 XQuery 資料類型或 SQL Server 資料類型。 下表顯示每一種資料類型支援的最佳化提示。

最佳化提示 XQuery 資料類型 SQL 資料類型
node() 是 否
單身人士 是 是
資料 TYPE 是 否
MAXLENGTH 是 否

node() 最佳化提示

適用於:XQuery 資料類型

您可以使用 node() 最佳化來指定一個在評估一般查詢時無須其值的節點。 這個提示可在一般查詢只需評估節點是否存在時,減少儲存需求 (根據預設,選擇性 XML 索引會儲存所有已升級節點的值,但是不包括複雜的節點類型)。

請考慮下列範例:

SELECT T.record FROM myXMLTable T
WHERE T.xmldata.exist('/a/b[./c=5]') = 1;

若要使用選擇性 XML 索引評估此查詢,請升級節點 b 和 c。 不過,由於不需要節點 b 的值,您可以使用下列語法的 node() 提示:

`/a/b/ as node()

如果查詢需要已利用 node() 提示編製索引之節點的值,則無法使用選擇性 XML 索引。

SINGLETON 最佳化提示

適用於:XQuery 或 SQL Server 資料類型

SINGLETON 最佳化提示會指定節點的基數。 此提示可改善查詢效能,因為事先就已知道節點最多只會在其父節點或祖先節點內出現一次。

請思考本文中的範例 XML 文件。

若要使用選擇性 XML 索引查詢此文件,您可以針對節點 d 指定 SINGLETON 提示,因為它最多只會在其父系內出現一次。

如果已指定 SINGLETON 提示,但節點在其父母或祖先內不只出現一次,則會在您建立索引(針對既有資料)或執行查詢(針對新資料)時出現錯誤。

DATA TYPE 最佳化提示

適用於:XQuery 資料類型

DATA TYPE 優化提示讓你可以為索引節點指定 XQuery 或 SQL Server 資料型別。 資料類型用於對應索引節點的選擇性 XML 索引之資料表中的資料行。

將現有值轉換成指定的資料類型失敗時,插入作業 (插入索引內) 不會失敗;但是會在索引的資料表中插入 null 值。

MAXLENGTH 最佳化提示

適用於:XQuery 資料類型

MAXLENGTH 最佳化提示可讓您限制 xs:string 資料的長度。 MAXLENGTH 與 SQL Server 資料類型無關,因為您是在指定 VARCHAR 或 NVARCHAR 資料類型時指定長度。

如果現有的字串長度超過指定的 MAXLENGTH,則將該值插入索引中的作業會失敗。

做為範例的範例 XML 文件

本文中的範例會參考下列範例 XML 文件:

<a>
    <b>
         <c atc="aa">10</c>
         <c atc="bb">15</c>
         <d atd1="dd" atd2="ddd">md </d>
    </b>
     <b>
        <c></c>
        <c atc="">117</c>
     </b>
</a>