2016-12-05 88 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的內部表示中找到使用該節點的節點並不會更快,而不是使用路徑表達式。至少沒有那麼快,以至於它補償了由於「交叉應用節點」而導致的額外函數調用的成本。 –