Estimativa deinalidade de predicados de intervalo parcialmente coberto


13

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:

Histograma

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:

insira a descrição da imagem aqui

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?


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

Respostas:


12

O SQL Server usa cálculos diferentes em diferentes situações. Seu exemplo é diferente das perguntas e respostas vinculadas porque seu intervalo está totalmente contido em uma etapa; não ultrapassa um limite de etapa. É também um intervalo com duas extremidades em vez de uma. Escrever BETWEENé o mesmo que escrever dois predicados separados com >=e <=.

Intervalo com dois limites, em uma única etapa

A fórmula é modificada para executar interpolação linear na etapa para o número de valores distintos esperados e reflete que dois pontos finais de intervalo agora estão especificados (e supõe-se que existam na etapa do histograma) em vez de um.

Usando as etapas do histograma fornecidas na pergunta:

questionar etapas do histograma

Para a consulta com BETWEEN '20140615' AND '20140616', o cálculo é:

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);

... dando 225,75 . Alterar @Q2de '20140616'para '20140617'fornece um resultado de 250.833 .

Ambos os resultados correspondem aos dados na pergunta.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.