2

我正在尝试优化依赖于XML变量输入的一些类型参数的存储过程。对执行计划的分析表明与访问这些参数中的数据相关的成本很高。

鉴于:

DECLARE @FirstNameXML  XML;

格式为

<FirstNames>
  <Name>John</Name>
  <Name>Joe</Name>
</FirstNames>

我需要执行一些操作(假设参数为非空):

提供的名称计数

SET @FirstNameCount = 
  (SELECT COUNT(FirstNameValues.Name.value('.','VARCHAR(50)'))
  FROM @FirstNameXML.nodes('/FirstNames/Name') 
  AS FirstNameValues(Name))

如果计数 = 1

...
AND First_Name LIKE
  (SELECT TOP(1) FirstNameValues.Name.value('.','VARCHAR(50)') + '%'
  FROM @FirstNameXML.nodes('/FirstNames/Name') 
  AS FirstNameValues(Name))
...

否则,如果计数 > 1

...
AND First_Name IN
(SELECT FirstNameValues.Name.value('.','VARCHAR(50)')
  FROM @FirstNameXML.nodes('/FirstNames/Name') 
  AS FirstNameValues(Name))
...

我尝试了一些优化:

将计数查询更改为

SET @FirstNameCount = 
  (SELECT CAST(CAST(@FirstNameXML.query('count(/FirstNames/Name)') 
    AS VARCHAR(10)) AS INT)

将 count == 1 查询更改为

...
AND First_Name LIKE
  (SELECT @FirstNameXML.value('(/FirstNames/Name)[1]', 'VARCHAR(50)') + '%')
...

不知何故,优化后存储过程运行得更慢,即使更改似乎降低了执行计划的成本。这给我留下了几个问题:

  1. 我是否误解了我实施的优化?
  2. 有没有更有效的方法来解决这个问题?(基于 XML 参数的查询)
4

1 回答 1

1

将 XML 中的行添加到表变量或临时表中。确保表变量/临时表的名称列上有索引。我也不认为需要对计数为 1 或多个时进行不同的查询。这样,您将只解析一次 XML。

笔记。当涉及到 XML 时,执行计划成本是不可信的。更好地测试set statistics time on和测量实际性能。

-- Test data
declare @FirstNameXML xml;
set @FirstNameXML = 
'<FirstNames>
  <Name>John</Name>
  <Name>Joe</Name>
</FirstNames>'

-- Put your data in a table variable.
-- Have Name as a primary key and you will get an index
declare @T table
(
  Name varchar(50) primary key
)

-- Add rows from XML to @T
insert into @T(Name)
select distinct T.N.value('.', 'varchar(50)')
from @FirstNameXML.nodes('FirstNames/Name') as T(N)

select *
from YourTable
where First_Name in (select Name from @T)
于 2012-05-25T05:43:53.750 回答