#sql-server #performance #xpath #xquery-sql
#sql-сервер #Производительность #xpath #xquery-sql
Вопрос:
Я делаю несколько грубых тестов с типом данных xml SQL Server 2008. Я видел много мест, где .exist
используется в where
предложениях. Недавно я сравнил два запроса и получил странные результаты.
select count(testxmlrid) from testxml
where Attributes.exist('(form/fields/field)[@id="1"]')=1
Выполнение этого запроса занимает около 1,5 секунд, без индексов для чего-либо, кроме первичного ключа (testxmlrid)
select count(testxmlrid) from testxml
where Attributes.value('(/form/fields/field/@id)[1]','integer')=1
Этот запрос с другой стороны занимает около .до запуска осталось 75 секунд.
Я использую нетипизированный XML, и мой бенчмаркинг выполняется на экземпляре SQL Server 2008 Express. В наборе данных около 15 000 строк, и каждая строка XML имеет длину около 25 строк.
Верны ли эти результаты, которые я получаю? Если да, то почему все используют .exist
? Я делаю что-то неправильно и .exist
могло бы быть быстрее?
Ответ №1:
Вы не учитываете одни и те же вещи. Ваш .exist
запрос (form/fields/field)[@id="1"]
проверяет все вхождения @id
в XML, пока не найдет одно со значением 1
, а ваш .value
запрос (/form/fields/field/@id)[1]
извлекает только первое вхождение @id
.
Протестируйте это:
declare @T table
(
testxmlrid int identity primary key,
Attributes xml
)
insert into @T values
('<form>
<fields>
<field id="2"/>
<field id="1"/>
</fields>
</form>')
select count(testxmlrid) from @T
where Attributes.exist('(form/fields/field)[@id="1"]')=1
select count(testxmlrid) from @T
where Attributes.value('(/form/fields/field/@id)[1]','integer')=1
Количество .exist
запросов равно 1, потому что оно находит @id=1
во втором field
узле, а количество .value
запросов равно 0, потому что оно проверяет значение только для первого вхождения @id
.
.exist
Запрос, который проверяет значение только при первом появлении @id
подобного вашему .value
запроса, будет выглядеть следующим образом.
select count(testxmlrid) from @T
where Attributes.exist('(/form/fields/field/@id)[1][.="1"]')=1
Комментарии:
1.
exist()
Не происходит короткого замыкания, как только оно находит первое вхождение в любом случае?2. @Yuck — Да, это так, но в этом случае
.exist
запрос ищет наличие@id=1
. Если первое вхождение if@id
отличается от 1, поиск продолжается..value
Запрос просматривает значение для первого вхождения@id
и не продолжает поиск, если это значение не равно 1.
Ответ №2:
Разница может заключаться в ваших индексах.
PATH
Индекс повысит производительность exist()
предиката в WHERE
предложении, тогда как PROPERTY
индекс повысит производительность value()
функции.
Прочитайте:http://msdn.microsoft.com/en-us/library/bb522562.aspx