Новость из категории: Информация

SQL Server: поиск или сканирование. Проблема возрастающего ключа. Продолжение

SQL Server: поиск или сканирование. Проблема возрастающего ключа. Продолжение

В версиях, предшествующих SQL Server 2014, при запрашивании диапазона значений ID заказов блок оценки числа элементов выполняет эту оценку по значениям, моделируемым гистограммой. Соответственно, при выходе диапазона фильтра за максимум, регистрируемый гистограммой, как правило, получается сильно заниженная оценка числа строк. Это может привести к тому, что оптимизатор будет делать неоптимальный выбор. Данную проблему можно продемонстрировать на примере приведенного ниже запроса. Запрос выполняется в SQL Server 2014, поэтому приходится указать флаг трассировки 9481, чтобы использовать более старую версию CE:
SELECT empid, COUNT (*) AS numorders
FROM dbo.Orders2
WHERE orderid > 900000
GROUP BY empid
OPTION (QUERYTRACE0N 9481);

SQL Server: поиск или сканирование. Проблема возрастающего ключа. Продолжение
План с заниженной оценкой числа элементов

План запроса приведен на скриншоте выше.

По гистограмме получается число строк, равное 1. В действительности должен получиться 0, но для блока оценки числа элементов допустимым оцениваемым минимумом является 1. Фактическое число — 100000. Следовательно, оптимизатор принимает ряд не самых удачных решений:
• вместо сканирования применяется поиск и много уточняющих запросов;
• вместо параллельного плана используется последовательный;
• вместо локального агрегата хеша с последующим глобальным агрегатом потока применяется сортировка с последующим применением агрегата потока;
• нет достаточного объема памяти, выделенной для операций сортировки, следствием чего являются два цикла сброса в tempdb.

Существует несколько способов исправления этой ситуации:
1. Добавить задание, предусматривающее более частое, выполняемое вручную обновление статистики столбца.
2. Включить флаг трассировки 2371, вынуждая SQL Server уменьшать выраженное в процентах значение, включенное в определение частоты обновления статистики, по мере увеличения числа строк. Подробнее об этом рассказано в статье http://blogs.msdn.com/b/saponsqlserver/archive/2011/09/07/changes-to-automatic-update-statistics-in-sql-server-traceflag-2371.aspx.
3. Включить флаг трассировки 2389, вынуждая SQL Server определять столбцы, которые являются возрастающим ключом, и для этих столбцов создавать в памяти мини-гистограмму, моделирующую последние изменения при перекомпиляции плана. Подробнее об этом рассказано в статье http://blogs.msdn.com/b/ianjo/archive/2006/04/24/582227.aspx.
4. Использовать SQL Server 2014. Новый блок оценки числа элементов определяет, когда фильтр запроса выходит за рамки максимального значения в гистограмме. Он имеет доступ к счетчику модификаций столбца (modctr), поэтому знает, сколько изменений было внесено с момента последнего обновления. Если столбец уникален и относится к целому или числовому типу, начиная с 0, SQL Server делает исходное предположение, что он является возрастающим. Поэтому оценка интерполируется на основе распределения значений в существующей гистограмме и числа изменений, имевших место с момента последнего обновления. В результате оценка получается более точной.

SQL Server: поиск или сканирование. Проблема возрастающего ключа. Продолжение
План с точной оценкой

Выполним в SQL Server 2014 следующий запрос без флага трассировки (план приведен на скриншоте выше), заставляющего использовать более старую версию блока оценки числа элементов:
SELECT empid, COUNT (*) AS numorders 
FROM dbo.Orders2
WHERE orderid > 900000
GROUP BY empid;

В приведенных выше примерах используется предикат orderid > 900000, не пересекающийся с максимальным значением на гистограмме (900000). Если же пересечение есть, то блок оценки числа элементов (CE) более старой версии берет исходную оценку, выполненную на основе существующей гистограммы, и пересчитывает ее с учетом значения счетчика modctr.

SQL Server: поиск или сканирование. Проблема возрастающего ключа. Продолжение

Например, для предиката orderid >= 900000 оценка числа элементов находится следующим образом:
1 x (1 + 100000/900000) = 1,11111. 

Для предиката orderid >= 899995 оценка вычисляется по-другому:
6 x (1 + 100000/900000) - 6,66666. 

Новый блок оценки использует метод интерполяции, аналогичный тому, что применяется в случае непересекающегося предиката. Например, для предиката orderid >= 900000 вычисляется точная оценка 100001, а для предиката orderid >= 899995 — точная оценка 100006.


<<К началу статьи

Рейтинг статьи

Оценка
0/5
голосов: 0
Ваша оценка статье по пятибальной шкале:
 
 
   

Поделиться

Похожие новости

Комментарии

^ Наверх