Оцінка чистоти частково охоплюючих предикатів


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 рядів.

Скажіть, будь ласка, як оцінює кардинальність в цьому випадку, можливо, я десь помилився в розумінні цитованих формул?


Сервер Sql 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.