使用Xquery从XML属性检索数据时的性能问题

时间:2012-09-10 11:01:21

标签: tsql xquery-sql

我有一个历史表,其中包含主表的事务记录信息,在此表中我使用XML列来存储该事务信息。具有数据的表结构看起来像。

Table information

在Content XML中,数据存储为xml,如下所示。

        <Answers>
      <AnswerSet>
        <Answer questionId="ProductCode">S3404</Answer>
        <Answer questionId="ProductName">Parabolic Triple</Answer>
        <Answer questionId="LegacyOptionID" selectedvalue="1389">1389</Answer>
        <Answer questionId="LegacyContentID" selectedvalue="624">624</Answer>
        <Answer questionId="LegacyPageID" selectedvalue="355">355</Answer>
        <Answer questionId="LegacyParentID" selectedvalue="760">760</Answer>
     </AnswerSet>
    </Answers>

在所有行结构相同但回答节点中的数据不同,我想获得具有ProductCode =“S3404”且CreatedDate为New的数据。

我创建了像

这样的查询
select n2.* from nodehistory n2 CROSS APPLY n2.content.nodes('Answers/AnswerSet') T(c) WHERE c.value('./Answer[@questionId="ProductCode"][1]','varchar(100)') ='J154'

ProductCode为每个nodeid都有唯一的数据,但这会为同一个nodeid返回多行,因为这是事务表,所以同一个XML可以存储多次,因为这需要条件,如Createddate desc的顺序,但执行此由于我认为XML处理,查询花费的时间更多。

首先我们可以通过CreatedDate desc从NodeHistory顺序中选择Top Top 1 nodeid,然后搜索XML部分。

请为您提供合适的观点以获得更好的表现

1 个答案:

答案 0 :(得分:0)

如果您对XML数据没有做太多其他工作,那么.exist应该比.value更有效。我认为BOL中有一个关于此的说明。您还可以使用sql:variable来使其更通用,例如:

declare @produceCode varchar(20) = 'S3404'

select n2.* 
from nodehistory n2 
    inner join ( select max(id) id from #nodehistory group by nodeId ) maxId ON n2.id = maxId.id
where n2.content.exist('Answers/AnswerSet/Answer[@questionId="ProductCode"][.=sql:variable("@produceCode")]') = 1

我使用子查询将结果集限制为每个nodeId的max(id)。您的要求可能略有不同,但您明白了。

就性能而言,XML索引可以转换SQL / XML查询,但需要付出代价。对于存储,您需要的原始尺寸是原始工作台的2-5倍,因此您必须权衡数据。如果您决定使用XML索引,那么PROPERTY索引应该有助于这种类型的查询,例如

-- create the primary XML index
CREATE PRIMARY XML INDEX xmlidx_nodehistory ON nodehistory(content)
GO

CREATE XML INDEX xmlprpidx_nodehistory ON nodehistory(content)
USING XML INDEX xmlidx_nodehistory FOR PROPERTY
go

declare @produceCode varchar(20) = 'S3404'

select n2.* 
from nodehistory n2 
    inner join ( select max(id) id from nodehistory group by nodeId ) maxId ON n2.id = maxId.id
where n2.content.exist('Answers/AnswerSet/Answer[@questionId="ProductCode"][.=sql:variable("@produceCode")]') = 1

有关更多SQL XML性能调优的想法,请参阅这些优秀文章:

SQL Server 2005中XML数据类型的性能优化

http://msdn.microsoft.com/en-us/library/ms345118.aspx

SQL Server 2005中的XML索引

http://msdn.microsoft.com/en-us/library/ms345121(SQL.90).aspx