Dan*_*her 6 performance index xml sql-server query-performance
我正在尝试为 1 亿行表中的 XML 列确定最有效的选择性 XML 索引。我的问题类似于:
用于选择性 Xml 索引的 Sql Server 2012 扩展事件未显示结果
但是答案中指定的选择性索引的具体好处没有详细讨论。
以下是查询的简化版本:
;WITH CTE AS
( SELECT 1 AS ID,
CONVERT(XML, '<Root>
<ParentTag ParentTagID="Sample Text">
<ChildTag1>5</ChildTag1>
<ChildTag1>6</ChildTag1>
<ChildTag1>7</ChildTag1>
<ChildTag2>8</ChildTag2>
<ChildTag2>9</ChildTag2>
<ChildTag2>10</ChildTag2>
<OtherTag>LargeIrrelevantData</OtherTag>
</ParentTag>
</Root>'
) AS SampleXML
)
SELECT * INTO dbo.CTE FROM CTE
SELECT ID,
Root.ParentTag.value('@ParentTagID','NVARCHAR(MAX)') AS ParentTagID,
RootParentTag1.ChildTag1.value('(text())[1]', 'NVARCHAR(MAX)') AS ChildTag1,
NULL
FROM CTE
OUTER APPLY CTE.SampleXML.nodes('/Root/ParentTag') as Root(ParentTag)
OUTER APPLY Root.ParentTag.nodes('ChildTag1') as RootParentTag1(ChildTag1)
UNION
SELECT ID,
Root.ParentTag.value('@ParentTagID','NVARCHAR(MAX)') AS ParentTagID,
NULL,
RootParentTag2.ChildTag2.value('(text())[1]', 'NVARCHAR(MAX)') AS ChildTag2
FROM CTE
OUTER APPLY CTE.SampleXML.nodes('/Root/ParentTag') as Root(ParentTag)
OUTER APPLY Root.ParentTag.nodes('ChildTag2') as RootParentTag2(ChildTag2)
Run Code Online (Sandbox Code Playgroud)
是最有效的索引:
EXEC sp_db_selective_xml_index [DATABASE], TRUE
ALTER TABLE CTE ADD CONSTRAINT PK_CTE PRIMARY KEY CLUSTERED (ID)
CREATE SELECTIVE XML INDEX SIX_CTE ON CTE(SampleXML)
FOR
( ParentTag = '/Root/ParentTag' AS XQUERY 'node()',
ParentTagChildTag1 = '/Root/ParentTag/ChildTag1' AS XQUERY 'node()',
ParentTagChildTag2 = '/Root/ParentTag/ChildTag2' AS XQUERY 'node()',
ParentTagID = '/Root/ParentTag/@ParentTagID' AS XQUERY 'xs:string' MAXLENGTH(255),
ChildTag1 = '/Root/ParentTag/ChildTag1/text()' AS XQUERY 'xs:double',
ChildTag2 = '/Root/ParentTag/ChildTag2/text()' AS XQUERY 'xs:double'
)
Run Code Online (Sandbox Code Playgroud)
我不希望LargeIrrelevantData
, 内的<OtherTag>
, 被索引。
我正在使用以下查询来跟踪 XML 中的索引列
SELECT
a.name AS column_name,
c.name AS data_type
FROM sys.columns a
INNER JOIN sys.indexes b
ON a.object_id = b.object_id
INNER JOIN sys.types c
ON a.system_type_id = c.user_type_id
WHERE b.name = 'SIX_CTE'
AND b.type = 1
ORDER BY column_id
Run Code Online (Sandbox Code Playgroud)
几个相关的问题:
除了查看查询执行时间之外,我还能如何确定选择性索引的性能提升?
在指定数据类型时,是首选使用 XQUERY 的 xs:double 还是 SQL 的 INT?
谢谢你。
除了查看查询执行时间之外,我还能如何确定选择性索引的性能提升?
您还可以查看 IO 利用率和 CPU。处理选择性 XML 索引时最有趣的可能是弄清楚查询是否实际使用了索引。为此,您可以查看执行计划。
如果您看到负责解析 XML 的表值函数之一,那么您就知道您没有使用 XML 索引覆盖您的 XML 查询。
相反,您应该在用于 XML 索引的内部表上使用扫描或查找运算符。
在指定数据类型时,是首选使用 XQUERY 的 xs:double 还是 SQL 的 INT?
如果您希望将索引用于value()
函数,您应该将索引中的数据类型与查询中使用的数据类型相匹配。您nvarchar(max)
在查询和xs:double
索引中都有ChildTag1
,ChildTag2
因此未在您的查询中使用。相反,它使用表值函数解析 XML 数据。
要使您的查询仅使用索引(无 xml 解析函数),您可以将查询和索引更改为此。
create selective xml index SIX_CTE on CTE(SampleXML) for
(
ParentTag = '/Root/ParentTag' as xquery 'node()',
ParentTagID = '/Root/ParentTag/@ParentTagID' as sql nvarchar(255),
ChildTag1 = '/Root/ParentTag/ChildTag1' as sql int,
ChildTag2 = '/Root/ParentTag/ChildTag2' as sql int
);
Run Code Online (Sandbox Code Playgroud)
请注意,您的查询不使用和上的node()
索引,因此索引中不需要。ChildTag1
ChildTag2
SELECT ID,
Root.ParentTag.value('@ParentTagID','NVARCHAR(255)') AS ParentTagID,
RootParentTag1.ChildTag1.value('.', 'INT') AS ChildTag1,
NULL
FROM CTE
OUTER APPLY CTE.SampleXML.nodes('/Root/ParentTag') as Root(ParentTag)
OUTER APPLY Root.ParentTag.nodes('ChildTag1') as RootParentTag1(ChildTag1)
UNION
SELECT ID,
Root.ParentTag.value('@ParentTagID','NVARCHAR(255)') AS ParentTagID,
NULL,
RootParentTag2.ChildTag2.value('.', 'INT') AS ChildTag2
FROM CTE
OUTER APPLY CTE.SampleXML.nodes('/Root/ParentTag') as Root(ParentTag)
OUTER APPLY Root.ParentTag.nodes('ChildTag2') as RootParentTag2(ChildTag2);
Run Code Online (Sandbox Code Playgroud)
什么是最有效的 SELECTIVE XML 索引?
完全取决于您的用例以及您拥有的数据。这个答案绝不是试图优化您的查询,只是向您展示如何使用索引的一种方式。对您的数据进行测试的结果可能表明,通过根本不使用任何索引或仅在查询的某些部分使用索引,您可以获得最佳性能。作为一般规则,保持索引尽可能小总是好的,因此如果您知道要处理整数int
,float
则使用代替是一件好事。