На даний момент я намагаюся з’ясувати, як 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 рядів.
Скажіть, будь ласка, як оцінює кардинальність в цьому випадку, можливо, я десь помилився в розумінні цитованих формул?