Estimación de la cardinalidad de predicados de rango que cubren parcialmente


13

En este momento estoy tratando de descubrir cómo SQL Server evalúa la cardinalidad de los predicados de rango que cubren parcialmente el paso del histograma.

En Internet, en cardinality-estimación-para-y-dentro-de-paso-estadística-valor me encontré con una pregunta similar y Paul White le dio una respuesta bastante interesante.

Según la respuesta de Paul, las fórmulas para estimar la cardinalidad para los predicados> = y> (en este caso, solo estoy interesado en el modelo de estimador de Cardinalidad de al menos 120) son las siguientes:

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

Probé la aplicación de estas fórmulas en la tabla [Producción]. [TransactionHistory] de la base de datos AdventureWorks2014 basada en el predicado de rango usando la columna TransactionDate y el rango de fecha y hora entre '20140614' y '20140618'.

Las estadísticas para el paso del histograma de este rango son las siguientes:

Histograma

De acuerdo con la fórmula, calculé la cardinalidad para la siguiente consulta:

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

El cálculo se realizó utilizando el siguiente 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]

Después de calcular, obtuve los siguientes resultados:

ingrese la descripción de la imagen aquí

De acuerdo con la fórmula, resultó 150.5, pero el optimizador estima el predicado en 225.75 filas, y si cambia el borde superior del predicado a '20140617', el optimizador ya evaluará 250.833 filas, mientras usa la fórmula solo obtenemos 200.6666 filas.

Por favor, dígame, ¿cómo evalúa Cardinality Estimator en este caso, tal vez cometí un error en algún punto de mi comprensión de las fórmulas citadas?


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

Respuestas:


12

SQL Server usa diferentes cálculos en diferentes situaciones. Su ejemplo es diferente de las preguntas y respuestas vinculadas porque su rango está completamente contenido en un paso; No cruza un límite escalonado. También es un intervalo con dos extremos en lugar de uno. Escribir BETWEENes lo mismo que escribir dos predicados separados con >=y <=.

Intervalo con dos límites, dentro de un solo paso.

La fórmula se modifica para realizar una interpolación lineal dentro del paso para la cantidad de valores distintos esperados, y refleja que ahora se especifican dos puntos finales de rango (y se supone que existen dentro del paso del histograma) en lugar de uno.

Usando los pasos del histograma dados en la pregunta:

pregunta los pasos del histograma

Para la consulta con BETWEEN '20140615' AND '20140616', el cálculo es:

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 . Cambiar @Q2de '20140616'a '20140617'da un resultado de 250.833 .

Ambos resultados coinciden con los dados en la pregunta.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.