2016-12-05 51 views
1

我有一个XML文件存储在我的表recordsXML数据类型列data中。SQL Server查询XML数据类型性能问题

表看起来是这样的:

create table records 
(
    id int, 
    type nvarchar(28), 
    data xml, 
    posted datetime 
) 

XML数据:

<Properties> 
    <data> 
     <Name>novel</Name> 
     <Gender>Female</Gender> 
     <Age>32</Age> 
     <Salary>55k</Salary> 
     <Phone>123-123</Phone> 
    </data> 
</Properties> 
我目前使用下面的查询,提取从XML列,其花费的时间比多分钟在20K记录数据

select 
    id, 
    posteddate, 
    CONVERT(NVARCHAR(500), data.query('data(Properties/data/Name)')) AS Name, 
    CONVERT(NVARCHAR(500), data.query('data(Properties/data/Gender)')) AS Gender, 
    CONVERT(NVARCHAR(500), data.query('data(Properties/data/Age)')) AS Age, 
    CONVERT(NVARCHAR(500), data.query('data(Properties/data/Salary)')) AS Salary, 
    CONVERT(NVARCHAR(500), data.query('data(Properties/data/Phone)')) AS Phone 
from 
    records 
where 
    type = 'personnel_xml' 

我很新来SQL Server中的XML提取。我想我没有遵循标准优化方法来提取XML元素。

那么,任何人都可以帮助我如何优化这种情况,因为我需要从我的xml中提取100个这样的元素存储为列。

回答

2

假设您在xml中有多个<data>。注意我添加了一个扩展的xml文件,它将有两组。

Declare @table table (id int,data xml) 
Insert Into @table values (1,'<Properties><data><Name>novel</Name><Gender>Female</Gender><Age>32</Age><Salary>55k</Salary><Phone>123-123</Phone></data> 
<data><Name>Another Name</Name><Gender>Male</Gender><Age>45</Age><Salary>75k</Salary><Phone>555-1212</Phone></data> 
</Properties>') 

;with cte as (
     Select ID 
      ,RN = Row_Number() over (Partition By ID Order By (Select Null)) 
      ,Data = m.query('.') 
     From @table AS t 
     Cross Apply t.Data.nodes('/Properties/data') AS A(m) 
) 
Select ID 
     ,RN 
     ,Name = Data.value('(data/Name)[1]' ,'nvarchar(500)') 
     ,Gender = Data.value('(data/Gender)[1]','nvarchar(500)') 
     ,Age = Data.value('(data/Age)[1]' ,'nvarchar(500)') 
     ,Salary = Data.value('(data/Salary)[1]','nvarchar(500)') 
     ,Phone = Data.value('(data/Phone)[1]' ,'nvarchar(500)') 
From cte 

返回

ID RN Name   Gender Age  Salary Phone 
1 1 novel   Female 32  55k  123-123 
1 2 Another Name Male 45  75k  555-1212 
+0

http://stackoverflow.com/users/1570000/john-cappelletti我的XML有单个数据元素,所以在这种情况下,我希望我不需要交叉应用。那么,从绩效的角度来看,应该选择哪一个,value()还是query()? – Aarush

+0

@JohnCappelleti在'temp表中存储整个xml并从#temp中提取'或'直接从table.column中提取而不使用#temp'的情况下,对于我没有重复的200s元素场景的性能差异属性 – Aarush

+0

@LearnByExample正确,因为你有单个数据元素,所以不需要交叉应用。因为你知道路径值比查询快。 –

2

为了得到一个值了XML的SQL Server中,你应该使用value() Method (xml Data Type)。对于无类型的XML,您应该指定text()节点以获得更好的性能。

select R.id, 
     R.posted, 
     R.data.value('(/Properties/data/Name/text())[1]', 'nvarchar(500)') as Name, 
     R.data.value('(/Properties/data/Gender/text())[1]', 'nvarchar(10)') as Gender, 
     R.data.value('(/Properties/data/Age/text())[1]', 'int') as Age, 
     R.data.value('(/Properties/data/Salary/text())[1]', 'nvarchar(10)') as Salary, 
     R.data.value('(/Properties/data/Phone/text())[1]', 'nvarchar(30)') as Phone 
from dbo.records as R 
where type = N'personnel_xml'; 
+1

嗨,你知道吗,如果引擎足够聪明的发现,'(/属性/数据/'在所有情况下是相同的?我认为这是更快或者使用像John Cappelletti在CTE中用'.query()',或者 - 甚至更好 - 在'.nodes(N'/ Properties/data')'上使用'CROSS APPLY',然后使用'.value()'名称/文本())[1]'。在这种情况下,它是否会反复遍历整个'XPath'? – Shnugo

+0

@Shnugo嗨,我已经做了一些关于使用'cross apply nodes'获取因为创建新XML的'UDX'操作符正在减慢速度,所以使用'query()'并不是什么好事,不知道这是否适用于*所有*形状和形式的XML,但它为我所尝试过的所有形式。 –

+0

@Shnugo顺便说一句,即使使用'cross apply nodes',整个XML也可用于值函数。你有一个叫做“上下文节点”的东西,它基本上是一个分层的ID,它被用作值函数的一个参数。显然,在XML的内部表示中找到使用该节点的节点并不会更快,而不是使用路径表达式。至少没有那么快,以至于它补偿了由于“交叉应用节点”而导致的额外函数调用的成本。 –