我有两个表,XMLtable
和filterTable
。
我需要来自XMLtable.ID
的所有XMLtable
值,其中Col_X
中的数据包含MyElement
,其内容与filterColumn
中的filterTable
相匹配}。
Col_X
中每行的XML可能包含多个MyElement
,如果这些元素中的任何一个与{{1}中的任何值匹配,我希望ID
}。
问题是这些列实际上是filterColumn
数据类型,并且表本身很大(如50GB巨大)。因此,此查询需要尽可能优化。
以下是我现在所处位置的示例,它仅返回第一个匹配元素等于我正在查找的行之一的行。由于过多的不同错误消息,我似乎无法将其更改为与我想要的所有相同的命名元素进行比较。
varchar(max)
...然后将结果与SELECT ID,
CAST(Col_X AS XML).value('(//*[local-name()=''MyElement''])', N'varchar(25)')
FROM XMLtable
进行比较。这已经花了5多分钟。
我想要达到的目标是:
filterTable
我目前唯一可以实现此目的的方法是使用LIKE运算符,这需要花费一千倍的时间。
现在,显然不能选择开始更改列的数据类型或其他任何内容。这是我必须要合作的。 :)
答案 0 :(得分:3)
试试这个:
SELECT
ID,
MyElementValue
FROM
(
SELECT ID, myE.value('(./text())[1]', N'VARCHAR(25)') AS 'MyElementValue'
FROM XMLTable
CROSS APPLY (SELECT CAST(Col_X AS XML)) as X(Col_X)
CROSS APPLY X.Col_X.nodes('(//*[local-name()="MyElement"])') as T2(myE)
) T1
WHERE MyElementValue IN (SELECT filterColumn FROM filterTable)
和此:
SELECT
ID,
MyElementValue
FROM
(
SELECT ID, myE.value('(./text())[1]', N'VARCHAR(25)') AS 'MyElementValue'
FROM XMLTable
CROSS APPLY (SELECT CAST(Col_X AS XML)) as X(Col_X)
CROSS APPLY X.Col_X.nodes('//MyElement') as T2(myE)
) T1
WHERE MyElementValue IN (SELECT filterColumn FROM filterTable)
<强>更新强>
我认为你正在体验这里所描述的内容Compute Scalars, Expressions and Execution Plan Performance。转换为XML将延迟到对value
函数的每次调用。您应该进行的测试是将Col_X
的数据类型更改为XML
。
如果这不是一个选项,您可以从XMLTable查询所需的行到具有XML列的临时表中,然后针对临时表执行上述查询,而无需转换为XML。
CREATE TABLE #XMLTable
(
ID int,
Col_X xml
)
INSERT INTO #XMLTable(ID, Col_X)
SELECT ID, Col_X
FROM XMLTable
SELECT
ID,
MyElementValue
FROM
(
SELECT ID, myE.value('(./text())[1]', N'varchar(25)') AS 'MyElementValue'
FROM #XMLTable
CROSS APPLY Col_X.nodes('//MyElement') as T2(myE)
) T1
WHERE MyElementValue IN (SELECT filterColumn FROM filterTable)
DROP TABLE #XMLTable
答案 1 :(得分:1)
你可以尝试这样的事情。我相信它至少在功能上做你想做的事。您必须根据经验探索其数据集的性能。
SELECT ID
FROM
(
SELECT xt.ID, CAST(xt.Col_X AS XML) [content] FROM XMLTable AS xt
) AS src
INNER JOIN FilterTable AS f
ON f.filterColumn IN
(
SELECT
elt.value('.', 'varchar(25)')
FROM src.content.nodes('//MyElement') AS T(elt)
)
答案 2 :(得分:0)
我终于有了这个工作,并且性能远远超出我的预期。下面是最终在5-6分钟内产生正确结果的脚本。
SELECT ID, myE.value('.', N'VARCHAR(25)') AS 'MyElementValue'
FROM (SELECT ID, CAST(Col_X AS XML) AS Col_X
FROM XMLTable) T1
CROSS APPLY Col_X.nodes('(//*[local-name()=''MyElement''])' T2(myE)
WHERE myE.value('.', N'varchar(25)') IN (SELECT filterColumn FROM filterTable)
感谢大家的帮助!