No momento, estou tentando descobrir como o SQL Server avalia a cardinalidade dos predicados de intervalo que cobrem parcialmente a etapa do histograma.
Na Internet, no valor da cardinalidade-estimativa-e-para-intra-passo-estatístico, deparei - me com uma pergunta semelhante e Paul White deu uma resposta bastante interessante a ela.
De acordo com a resposta de Paulo, as fórmulas para estimar a cardinalidade para os predicados> = e> (neste caso, estou interessado apenas no modelo do estimador de cardinalidade de pelo menos 120) são as seguintes:
Para>:
Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * (F * (DISTINCT_RANGE_ROWS - 1)))
Para> =:
Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1))
Testei a aplicação dessas fórmulas na tabela [Production]. [TransactionHistory] do banco de dados AdventureWorks2014 com base no predicado de intervalo usando a coluna TransactionDate e o intervalo de tempo entre '20140614' e '20140618'.
As estatísticas para a etapa do histograma desse intervalo são as seguintes:
De acordo com a fórmula, calculei a cardinalidade para a seguinte consulta:
SELECT COUNT(1)
FROM [AdventureWorks2014].[Production].[TransactionHistory]
WHERE [TransactionDate] BETWEEN '20140615 00:00:00.000' AND '20140616 00:00:00.000'
O cálculo foi realizado usando o seguinte código:
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]
Após o cálculo, obtive os seguintes resultados:
De acordo com a fórmula, resultou em 150,5, mas o otimizador estima o predicado em 225,75 linhas, e se você alterar a borda superior do predicado para '20140617', o otimizador já avaliará 250,833 linhas, enquanto usa a fórmula, obtemos apenas 200.6666 linhas.
Por favor, diga-me, como o Cardinality Estimator avalia neste caso, talvez eu tenha cometido um erro em algum lugar no meu entendimento das fórmulas citadas?