适用于:SQL Server
Azure SQL 数据库
Azure SQL 托管实例
本文介绍如何在创建或更改选择性 XML 索引时指定索引的节点路径以及索引的优化提示。
您可以在以下语句之一中同时指定节点路径和优化提示:
- 在 CREATE 语句的 FOR 子句中。 有关详细信息,请参阅 CREATE SELECTIVE XML INDEX (Transact-SQL)。 
- 在 ALTER 语句的 ADD 子句中。 有关详细信息,请参阅 ALTER INDEX(选择性 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() 数据类型的  方法的 SQL Server 类型系统之间存在细微差异。 这些差异如下:
- XQuery 类型系统知道尾随空格。 根据 XQuery 类型语义,字符串“abc”和“abc”不相等,而在 SQL Server 这两个字符串是相等的。 
- XQuery 浮点数据类型支持 +/- 零和 +/- 无穷大的特殊值。 SQL Server 浮点数据类型不支持这些特殊值。 
非类型化 XML 中的 XQuery 类型
- XQuery 类型与 xml 数据类型的所有方法(包括 - value()方法)中的 XQuery 表达式匹配。
- 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;
该指定的查询从打包到 NVARCHAR(200) 数据类型中的路径 /a/b/d 返回一个值,因此,要为该节点指定的数据类型十分明显。 但是,没有用于在非类型化 XML 中指定节点基数的架构。 若要指定节点 d 在其父节点 b下最多出现一次,请创建一个选择性 XML 索引,该索引使用 SINGLETON 优化提示,如下所示:
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:若要评估某一给定的 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:为了得到最佳性能,为对某一给定 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 | 在 FLWOR 子句中为节点 f的值进行求值。 | 
| /a/b/c/d/e/g | 通过 g方法为存在的节点exist()进行求值。 | 
指定优化提示
您可以使用可选的优化提示为按选择性 XML 索引建立索引的节点指定附加的映射详细信息。 例如,可以指定节点的数据类型和基数,以及与数据结构有关的某些信息。 这些附加信息支持更好的映射。 它还可以导致改进性能和/或节约存储空间。
是否使用优化提示是可选的。 您可以始终接受默认映射,这样做是可靠的,但无法提供最佳性能和存储。
某些优化提示(例如 SINGLETON 提示)会引入针对数据的约束。 在某些情况下,如果不满足这些约束,可能会引发错误。
优化提示的好处
下表标识支持更高效的存储或改进的性能的优化提示。
| 优化提示 | 更高效的存储 | 提升了性能 | 
|---|---|---|
| node() | 是 | 否 | 
| 单身 人士 | 否 | 是 | 
| 数据类型 | 是 | 是 | 
| MAXLENGTH | 是 | 是 | 
优化提示和数据类型
可以将节点作为 XQuery 数据类型或 SQL Server 数据类型建立索引。 下表显示了每种数据类型支持的优化提示。
| 优化提示 | XQuery 数据类型 | SQL 数据类型 | 
|---|---|---|
| node() | 是 | 否 | 
| 单身 人士 | 是 | 是 | 
| 数据类型 | 是 | 否 | 
| 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>