Tsql 使用Xquery从XMLAttribute检索数据时的性能问题

Tsql 使用Xquery从XMLAttribute检索数据时的性能问题,tsql,xquery-sql,Tsql,Xquery Sql,我有一个历史表,其中包含主表的事务记录信息,在这个表中,我使用XML列存储该事务信息。包含数据的表结构如下所示 在内容中,XML数据存储为XML,如下所示 <Answers> <AnswerSet> <Answer questionId="ProductCode">S3404</Answer> <Answer questionId="ProductName">Paraboli

我有一个历史表,其中包含主表的事务记录信息,在这个表中,我使用XML列存储该事务信息。包含数据的表结构如下所示

在内容中,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对每个nodeid都有唯一的数据,但这会为同一nodeid返回多行数据,因为这是事务表,所以同一XML可以多次存储,对于这一要求条件,如order by Createddate desc,但我认为由于XML处理,执行此查询需要更多时间

我们能像第一次一样吗

Select Top 1 nodeid from NodeHistory order by CreatedDate desc
然后搜索XML部分


关于更合适的视图以获得更好的性能,您有什么想法吗?

如果您对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
我使用子查询将resultset限制为每个节点id的最大值(id)。你的要求可能略有不同,但你明白了

就性能而言,XML索引可以转换SQL/XML查询,但代价很高。对于存储,您将需要原始表大小的2-5倍,因此您必须使用数据对其进行权衡。如果您决定使用XML索引,那么属性索引应该有助于此类查询,例如

-- 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性能调优的更多想法,请参阅这些优秀文章:

SQLServer2005中XML数据类型的性能优化

SQLServer2005中的XML索引

-- 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