2016-12-05 2 views
1

У меня есть файл XML, хранящийся в столбце XML типа данных data в моей таблице records.Ошибка SQL-запроса на запрос производительности 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' 

Я очень новичок в извлечении XML в SQL Server. Я предполагаю, что не выполняю стандартный оптимизированный подход для извлечения элементов XML.

Итак, может ли кто-нибудь помочь, как я могу оптимизировать этот сценарий, поскольку мне нужно извлечь 100 таких элементов из моего xml, хранящихся в виде столбца.

ответ

2

Предполагая, что у вас есть несколько <data> внутри xml. Заметьте, я добавил расширенный 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 my xml имеет один элемент данных, поэтому в этом случае я надеюсь, что мне не нужен крест. Итак, с точки зрения производительности, которую нужно выбрать, value() или query()? – Aarush

+0

@JohnCappelleti, какова разница в производительности в 'хранении всего xml в таблице #temp и извлечении из #temp' OR ', непосредственно извлечении из table.column без использования #temp для моего сценария из 200 элементов без повторения атрибут – 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

Привет, знаете ли вы, если двигатель достаточно умен, чтобы найти, что '(/ Свойства/данные /' одинаково во всех случаях? Я думал, что было бы быстрее использовать что-то вроде Джона Каппеллетти с '.query()' в CTE, или - еще лучше - 'CROSS APPLY' на' .nodes (N '/ Properties/data') ', а затем использовать' .value() 'on' (Имя/текст()) [1] '. Не будет ли он перемещаться по всему« XPath »снова и снова в этом случае? – Shnugo

+0

@Shnugo Привет, Я провел некоторое тестирование производительности, используя« cross apply nodes », чтобы получить более короткое выражение в функции значений и медленнее (не так много). Использование 'query()' не очень хорошо, поскольку оператор 'UDX', который создает новый XML, замедляет работу. Не уверен, что это верно для * все * формы и формы XML, но он делает все, что я пробовал. –

+0

@Shnugo BTW, весь XML доступен для функции значений, даже если вы используете «cross apply nodes». W у вас есть что-то, называемое «узлом контекста», который в основном представляет собой иерархический идентификатор, который используется как параметр функции значения. По-видимому, не намного быстрее найти узлы, используя это вместо выражения пути во внутреннем представлении XML. По крайней мере, не так быстро, что он компенсирует стоимость дополнительного вызова функции из-за «кросс-приложений». –

Смежные вопросы