2

我有两张桌子,XMLtablefilterTable

我需要其中数据包含的所有XMLtable.ID值,其中的内容与.XMLtableCol_XMyElementfilterColumnfilterTable

中每一行的 XMLCol_X可能包含多个MyElement's,ID如果这些元素中的任何一个与filterColumn.

问题是这些列实际上是varchar(max)数据类型,并且表本身很大(比如 50GB 巨大)。所以这个查询需要尽可能的优化。

这是我现在所在位置的示例,它仅返回第一个匹配元素等于我正在寻找的元素之一的行。由于过多的不同错误消息,我似乎无法将其更改为与我想要的所有相同命名的元素进行比较。

SELECT ID, 
   CAST(Col_X AS XML).value('(//*[local-name()=''MyElement''])', N'varchar(25)') 
FROM  XMLtable

...然后将结果与filterTable. 这已经需要 5 分钟以上。

我想要实现的是:

SELECT ID
FROM XMLtable
WHERE CAST(Col_X AS XML).query('(//*[local-name()=''MyElement''])') 
   IN (SELECT filterColumn FROM filterTable)

我目前能做到这一点的唯一方法是使用 LIKE 运算符,这需要大约一千倍的时间。

现在,显然它不是开始更改列的数据类型或其他任何东西的选项。这是我必须处理的。:)

4

3 回答 3

4

尝试这个:

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_XXML

如果这不是一个选项,您可以将所需的行从 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
于 2012-10-02T15:31:32.790 回答
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)
)
于 2012-09-28T13:29:09.490 回答
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)

感谢人们的帮助!

于 2012-10-02T13:26:57.277 回答