Счетчик SQL Server 2014 (DISTINCT x) игнорирует вектор плотности статистики для столбца x

15

Для a, COUNT(DISTINCT)который имеет ~ 1 миллиард различных значений, я получаю план запроса с агрегатом хешей, который оценивается в ~ 3 миллиона строк.

Почему это происходит? SQL Server 2012 дает хорошую оценку, так что это ошибка в SQL Server 2014, о которой я должен сообщить в Connect?

Запрос и плохая оценка

-- Actual rows: 1,011,719,166
-- SQL 2012 estimated rows: 1,079,130,000 (106% of actual)
-- SQL 2014 estimated rows: 2,980,240 (0.29% of actual)
SELECT COUNT(DISTINCT factCol5)
FROM BigFactTable
OPTION (RECOMPILE, QUERYTRACEON 9481) -- Include this line to use SQL 2012 CE

-- Stats for the factCol5 column show that there are ~1 billion distinct values
-- This is a good estimate, and it appears to be what the SQL 2012 CE uses
DBCC SHOW_STATISTICS (BigFactTable, _WA_Sys_00000005_24927208)
--All density   Average Length  Columns
--9.266754E-10  8               factCol5
SELECT 1 / 9.266754E-10
-- 1079126520.46229

План запроса

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

Полный сценарий

Вот полное воспроизведение ситуации с использованием базы данных только для статистики .

Что я пробовал до сих пор

Я копался в статистике для соответствующего столбца и обнаружил, что вектор плотности показывает приблизительно 1,1 миллиарда различных значений. SQL Server 2012 использует эту оценку и вырабатывает хороший план. Удивительно, но SQL Server 2014 игнорирует очень точную оценку, предоставленную статистикой, и вместо этого использует гораздо более низкую оценку. Это приводит к гораздо более медленному плану, который не резервирует почти достаточно памяти и разливает для tempdb.

Я попробовал трассировать флаг 4199, но это не исправило ситуацию. Наконец, я попытался найти информацию оптимизатора с помощью комбинации флагов трассировки (3604, 8606, 8607, 8608, 8612), как показано во второй половине этой статьи . Однако я не смог увидеть какую-либо информацию, объясняющую неверную оценку, пока она не появилась в конечном итоговом дереве.

Проблема с подключением

Основываясь на ответах на этот вопрос, я также подал это как проблему в Connect

Джефф Паттерсон
источник

Ответы:

14

То, как выводится оценка мощности, конечно, кажется мне нелогичным. Вычисление отдельного подсчета (доступное для просмотра с помощью расширенных событий или флагов трассировки 2363 и 3604):

Вывод статистики

Обратите внимание на шапку. Общая логика этого кажется очень разумной (не может быть более четких значений), но ограничение применяется из выборочной статистики из нескольких столбцов:

DBCC SHOW_STATISTICS 
    (BigFactTable, [PK_BigFactTable])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

ПК Статистика

Это показывает 2 980 235 строк, отобранных из 3 439 431 721 с вектором плотности на уровне Col5 3.35544E-07. Обратная величина этого дает ряд различных значений от 2 980 235, округленных с использованием реальной математики до 2 980 240.

Теперь вопрос, учитывая выборочную статистику, какие предположения должна сделать модель относительно числа различных значений. Я ожидал бы, что это экстраполирует, но это не сделано, и возможно преднамеренно.

Более интуитивно, я бы ожидал, что вместо использования статистики по нескольким столбцам он будет смотреть на плотность на Col5 (но это не так):

DBCC SHOW_STATISTICS 
    (BigFactTable, [_WA_Sys_00000005_24927208])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

Статистика Col5

Здесь плотность составляет 9,266754E-10, обратная величина которой составляет 1,079,122,528 .

В то же время одним из очевидных обходных путей является обновление статистики по нескольким столбцам с полным сканированием. Другой заключается в использовании оригинальной оценки кардинальности.

Открывшийся элемент «Соединение», в котором выборочная многостолбцовая статистика SQL 2014 переопределяет более точную одностолбцовую статистику для не ведущих столбцов , помечен как исправленный для SQL Server 2017.

Пол Уайт восстановил Монику
источник