cub*_*729 2 xml sql-server sql-server-2012 xquery
假设我有以下 XML 数据,其中
<root>
可以有任意数量的<child>
孩子<child>
可以有任意数量的<grandchild>
孩子<grandchild>
可以有任意数量的<greatgrandchild>
孩子<child>
并且<grandchild>
可以有任意数量的<parameter>
孩子<parameter>
都有<name>
一个<value>
孩子例如,
<root name="root">
<child name="a">
<grandchild name="a1">
<parameter>
<name>param1</name>
<value>ABC123</value>
</parameter>
<parameter>
<name>param2</name>
<value>CBC</value>
</parameter>
<greatgrandchild name="a1a">
<parameter>
<name>paramA</name>
<value>ABC</value>
</parameter>
<parameter>
<name>paramB</name>
<value>DBC</value>
</parameter>
</greatgrandchild>
</grandchild>
</child>
</root>
Run Code Online (Sandbox Code Playgroud)
我需要做的是选择包含“_BC”的值的参数,其中 _ 是一个不是 A 的字符。
我有以下查询
SELECT
TestId,
[root],
child,
grandchild,
NULL AS greatgrandchild,
parameter
FROM (
SELECT
TestId,
[root].a.value('@name', 'varchar(max)') AS [root],
child.b.value('@name', 'varchar(max)') AS child,
grandchild.c.value('@name', 'varchar(max)') AS grandchild,
parameter.d.value('(name)[1]', 'varchar(max)') AS parameter,
parameter.d.value('(value)[1]', 'varchar(max)') AS parameter_value
FROM
dbo.TestTable
CROSS APPLY TestData.nodes('/root') AS [root](a)
CROSS APPLY [root].a.nodes('child') AS child(b)
CROSS APPLY child.b.nodes('grandchild') AS grandchild(c)
CROSS APPLY grandchild.c.nodes('parameter') AS parameter(d)
) t
WHERE
parameter_value LIKE '%[^Aa]BC%'
UNION ALL
SELECT
TestId,
[root],
child,
grandchild,
greatgrandchild,
parameter
FROM (
SELECT
TestId,
[root].a.value('@name', 'varchar(max)') AS [root],
child.b.value('@name', 'varchar(max)') AS child,
grandchild.c.value('@name', 'varchar(max)') AS grandchild,
greatgrandchild.d.value('@name', 'varchar(max)') AS greatgrandchild,
parameter.e.value('(name)[1]', 'varchar(max)') AS parameter,
parameter.e.value('(value)[1]', 'varchar(max)') AS parameter_value
FROM
dbo.TestTable
CROSS APPLY TestData.nodes('/root') AS [root](a)
CROSS APPLY [root].a.nodes('child') AS child(b)
CROSS APPLY child.b.nodes('grandchild') AS grandchild(c)
CROSS APPLY grandchild.c.nodes('greatgrandchild') AS greatgrandchild(d)
CROSS APPLY greatgrandchild.d.nodes('parameter') AS parameter(e)
) t
WHERE
parameter_value LIKE '%[^Aa]BC%'
Run Code Online (Sandbox Code Playgroud)
例如,对于以下测试数据:
CREATE TABLE TestTable (
TestId INT PRIMARY KEY,
TestData XML NOT NULL
);
INSERT INTO dbo.TestTable (TestId, TestData)
VALUES (1, '<root name="root">
<child name="a">
<grandchild name="a1">
<parameter>
<name>param1</name>
<value>ABC123</value>
</parameter>
<parameter>
<name>param2</name>
<value>CBC</value>
</parameter>
<greatgrandchild name="a1a">
<parameter>
<name>paramA</name>
<value>ABC</value>
</parameter>
<parameter>
<name>paramB</name>
<value>DBC</value>
</parameter>
</greatgrandchild>
</grandchild>
</child>
</root>');
Run Code Online (Sandbox Code Playgroud)
应返回以下结果集:
TestId root child grandchild greatgrandchild parameter
------------------------------------------------------
1 root a a1 NULL param2
1 root a a1 a1a paramB
Run Code Online (Sandbox Code Playgroud)
我想知道我的 SELECT 查询是否可以优化
在每行 20KB XML 数据的 400 行表上,SELECT 查询需要 40 分钟。无法更改 XML 布局。
这是对您已有内容的重写。
text()
参数名称和参数值的节点。在我有限的测试中,这使它明显更快。我期待着看到您在您身边看到的任何性能提升。
select T.TestId,
T.TestData.value('(/root/@name)[1]', 'varchar(max)') as [root],
C.X.value('@name', 'varchar(max)') as child,
GC.X.value('@name', 'varchar(max)') as grandchild,
null as greatgrandchild,
P.X.value('(name/text())[1]', 'varchar(max)') as parameter
from dbo.TestTable as T
cross apply T.TestData.nodes('/root/child') as C(X)
cross apply C.X.nodes('grandchild') as GC(X)
cross apply GC.X.nodes('parameter') as P(X)
where P.X.value('(value/text())[1]', 'varchar(max)') like '%[^Aa]BC%'
union all
select T.TestId,
T.TestData.value('(/root/@name)[1]', 'varchar(max)') as [root],
C.X.value('@name', 'varchar(max)') as child,
GC.X.value('@name', 'varchar(max)') as grandchild,
GGC.X.value('@name', 'varchar(max)') as greatgrandchild,
P.X.value('(name/text())[1]', 'varchar(max)') as parameter
from dbo.TestTable as T
cross apply T.TestData.nodes('/root/child') as C(X)
cross apply C.X.nodes('grandchild') as GC(X)
cross apply GC.X.nodes('greatgrandchild') as GGC(X)
cross apply GGC.X.nodes('parameter') as P(X)
where P.X.value('(value/text())[1]', 'varchar(max)') like '%[^Aa]BC%'
Run Code Online (Sandbox Code Playgroud)
更新:
我冒昧地在兼容级别为 110 (SQL Server 2012) 和 120 (SQL Server 2014) 的 SQL Server 2014 上执行 wBob 提供的测试装置
结果:
Compatibility level OP's query My query wBob query using XML indexes
------------------- ---------- -------- ----------------------------
110 64 sec 37 sec 1 sec
120 8 sec 4 sec 5 sec
Run Code Online (Sandbox Code Playgroud)
您看到的执行时间差异是因为 SQL Server 2014 使用新的基数估计器。当兼容级别为 110 时,SQL Server 将使用旧的估算器。使用跟踪标志打开或关闭新的基数估计器会产生完全相同的结果。
不使用 XML 索引的查询的时间差异是因为在兼容性级别 120 中,在我的情况下,计划与 DOP 16 并行。
值得注意的是,使用新的基数估计器时,使用 XML 索引的执行时间要慢五倍。其原因与上述相同,只是相反。只有在使用旧的基数估计器时才有并行计划。
归档时间: |
|
查看次数: |
1321 次 |
最近记录: |