Расчетные и фактические различия строк (фактические значительно меньше, чем предполагаемые) - сортировка

8

Я выполняю запрос, который обрабатывает некоторые узлы из документа XML. Моя приблизительная стоимость поддерева исчисляется миллионами, и кажется, что все это происходит из-за операции сортировки, которую sql-сервер выполняет над некоторыми данными, которые я извлекаю из столбцов xml через XPath. Операция Sort имеет приблизительное число строк, равное приблизительно 19 миллионам, тогда как фактическое количество строк составляет около 800. Сам запрос выполняется достаточно хорошо (1 - 2 секунды), но расхождение заставляет меня задуматься о производительности запроса и почему разница такая большая?

Питер Смит
источник
2
Возможно, это связано с устаревшей статистикой, но на самом деле ее невозможно определить без дополнительной информации (включая структуру / индексы таблицы, запрос и фактический, а не оцененный, план выполнения).
Аарон Бертран
1
Исходя из моего опыта, планы запросов, которые включают в себя измельчение XML, всегда имеют сильно завышенные оценки затрат. Например, если запрос работает хорошо с точки зрения времени выполнения, я просто игнорирую оценки стоимости. Я понятия не имею, почему это так, но это может быть связано с незнанием того, сколько XML будет использоваться в качестве входных данных. Если ваша цель - повысить производительность запроса, то я нашел один из способов сделать это - использовать коллекции XML-схем, о которых я писал здесь .
Джон Зигель

Ответы:

9

Статистика по столбцам XML не генерируется. Оценки предполагаются на основе выражений, используемых при запросе XML.

Используя эту таблицу:

create table T(XMLCol xml not null)
insert into T values('<root><item value = "1" /></root>')

И этот довольно простой XML-запрос:

select X.N.value('@value', 'int')
from T
  cross apply T.XMLCol.nodes('root/item') as X(N)

Даст вам одну возвращаемую строку, но оценочные возвращенные строки будут равны 200. Это будет 200 независимо от того, какой XML или сколько XML вы вставляете в столбец XML для этой одной строки.

Это план запроса с отображаемым предполагаемым количеством строк.

введите описание изображения здесь

Чтобы улучшить или хотя бы изменить оценки, можно предоставить оптимизатору запросов дополнительную информацию о XML. В этом случае, поскольку я знаю, что это rootдействительно корневой узел в XML, я могу переписать запрос следующим образом.

select X2.N.value('@value', 'int')
from T
  cross apply T.XMLCol.nodes('root[1]') as X1(N)
  cross apply X1.N.nodes('item') X2(N)

Это даст мне оценку 5 возвращенных строк.

введите описание изображения здесь

Переписывание запроса, вероятно, не ускорит уничтожение XML, но если оценки будут лучше, есть вероятность, что оптимизатор запросов может принимать более разумные решения для остальной части запроса.

Я не нашел никакой документации о правилах оценки, кроме презентации Майкла Риса, где он говорит:

Базовая оценка кардинальности всегда 10 000 строк!
Некоторая корректировка на основе проталкиваемых фильтров пути

Микаэль Эрикссон
источник