Оценка мощности предикатов частично охватывающего диапазона


13

Сейчас я пытаюсь выяснить, как SQL Server оценивает количество предикатов диапазона, которые частично покрывают шаг гистограммы.

В интернете, при значении статистики кардинальности для оценки внутри шага, я наткнулся на похожий вопрос, и Пол Уайт дал на него довольно интересный ответ.

Согласно ответу Павла, формулы для оценки количества элементов для предикатов> = и> (в данном случае меня интересует только модель оценки мощности по крайней мере 120):

Для>:

Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * (F * (DISTINCT_RANGE_ROWS - 1)))

Для> =:

Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1))

Я протестировал применение этих формул в таблице [Production]. [TransactionHistory] базы данных AdventureWorks2014 на основе предиката диапазона с использованием столбца TransactionDate и диапазона даты и времени между «20140614» и «20140618».

Статистика шага гистограммы этого диапазона следующая:

Гистограмма

По формуле я рассчитал количество элементов для следующего запроса:

SELECT COUNT(1)
FROM [AdventureWorks2014].[Production].[TransactionHistory]
WHERE [TransactionDate] BETWEEN '20140615 00:00:00.000' AND '20140616 00:00:00.000'

Расчет был выполнен с использованием следующего кода:

  DECLARE @predStart DATETIME =  '20140615 00:00:00.000'
  DECLARE @predEnd DATETIME = '20140616 00:00:00.000'

  DECLARE @stepStart DATETIME = '20140614 00:00:00.000'
  DECLARE @stepEnd DATETIME = '20140618 00:00:00.000'

  DECLARE @predRange FLOAT = DATEDIFF(ms, @predStart, @predEnd)
  DECLARE @stepRange FLOAT = DATEDIFF(ms, @stepStart, @stepEnd)

  DECLARE @F FLOAT = @predRange / @stepRange;

  DECLARE @avg_range_rows FLOAT = 100.3333
  DECLARE @distinct_range_rows INT = 3
  DECLARE @EQ_ROWS INT = 0

  SELECT @F AS 'F'

  --for new cardinality estimator

  SELECT @EQ_ROWS + @avg_range_rows * (@F * (@distinct_range_rows - 1) + 1) AS [new_card]

После расчета я получил следующие результаты:

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

Согласно формуле получилось 150,5, но оптимизатор оценивает предикат в 225,75 строк, и если вы измените верхнюю границу предиката на «20140617», оптимизатор уже оценит 250,833 строк, при этом по формуле мы получаем только 200,6666 строк.

Скажите, пожалуйста, как оценивает Cardinality Estimator в этом случае, может быть, я где-то допустил ошибку в моем понимании приведенных формул?


Sql server 2014 12.0.5 SP2
Павел Ковалёв

Ответы:


12

SQL Server использует разные вычисления в разных ситуациях. Ваш пример отличается от связанных вопросов и ответов, потому что ваш диапазон целиком содержится в шаге; он не пересекает границу шага. Это также интервал с двумя концами, а не с одним. Написание BETWEENаналогично написанию двух отдельных предикатов с помощью >=и <=.

Интервал с двумя границами, в пределах одного шага

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

Используя шаги гистограммы, приведенные в вопросе:

шаги гистограммы вопроса

Для запроса с BETWEEN '20140615' AND '20140616'вычислением:

DECLARE
    @Q1 float = CONVERT(float, CONVERT(datetime, '2014-06-15')),
    @Q2 float = CONVERT(float, CONVERT(datetime, '2014-06-16')),
    @K1 float = CONVERT(float, CONVERT(datetime, '2014-06-14')),
    @K2 float = CONVERT(float, CONVERT(datetime, '2014-06-18')),
    @RANGE_ROWS float = 301,
    @DISTINCT_RANGE_ROWS float = 3;

DECLARE
    @S1 float = (@Q1 - @K1) / (@K2 - @K1),
    @S2 float = (@Q2 - @K1) / (@K2 - @K1);

DECLARE
    @F float = @S2 - @S1;

DECLARE
    @AVG_RANGE_ROWS float = @RANGE_ROWS / @DISTINCT_RANGE_ROWS;

SELECT
    @AVG_RANGE_ROWS * ((@F * (@DISTINCT_RANGE_ROWS - 2)) + 2);

... давая 225,75 . Переход @Q2от '20140616'к '20140617'дает результат 250.833 .

Оба результата соответствуют приведенным в вопросе.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.