En ce moment, j'essaie de comprendre comment SQL Server évalue la cardinalité des prédicats de plage qui couvrent partiellement l'étape d'histogramme.
Sur Internet, à cardinality-estimation-for-and-intra-step-statistics-value, je suis tombé sur une question similaire et Paul White a donné une réponse plutôt intéressante.
Selon la réponse de Paul, les formules d'estimation de la cardinalité pour les prédicats> = et> (dans ce cas, je ne suis intéressé que par le modèle d'estimation de la cardinalité d'au moins 120) sont les suivantes:
Pour>:
Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * (F * (DISTINCT_RANGE_ROWS - 1)))
Pour> =:
Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1))
J'ai testé l'application de ces formules sur la table [Production]. [TransactionHistory] de la base de données AdventureWorks2014 basée sur le prédicat de plage à l'aide de la colonne TransactionDate et de la plage de datetime entre '20140614' et '20140618'.
Les statistiques de l'étape d'histogramme de cette plage sont les suivantes:
Selon la formule, j'ai calculé la cardinalité pour la requête suivante:
SELECT COUNT(1)
FROM [AdventureWorks2014].[Production].[TransactionHistory]
WHERE [TransactionDate] BETWEEN '20140615 00:00:00.000' AND '20140616 00:00:00.000'
Le calcul a été effectué à l'aide du code suivant:
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]
Après le calcul, j'ai obtenu les résultats suivants:
Selon la formule, il s'est avéré 150,5, mais l'optimiseur estime le prédicat à 225,75 lignes, et si vous changez la bordure supérieure du prédicat en '20140617', l'optimiseur évaluera déjà 250,833 lignes, tout en utilisant la formule que nous obtenons uniquement 200,6666 lignes.
Veuillez me dire, comment Cardinality Estimator évalue-t-il dans ce cas, peut-être que j'ai fait une erreur quelque part dans ma compréhension des formules citées?