Al momento sto cercando di capire come SQL Server valuta la cardinalità dei predicati di intervallo che coprono parzialmente il passaggio dell'istogramma.
Su Internet, alla stima della cardinalità-per-e-per-intra-step-valore-statistica ho incontrato una domanda simile e Paul White ha dato una risposta piuttosto interessante ad essa.
Secondo la risposta di Paul, le formule per stimare la cardinalità per i predicati> = e> (in questo caso, sono interessato solo al modello dello stimatore della cardinalità di almeno 120) sono le seguenti:
Per>:
Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * (F * (DISTINCT_RANGE_ROWS - 1)))
Per> =:
Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1))
Ho testato l'applicazione di queste formule sulla tabella [Production]. [TransactionHistory] del database AdventureWorks2014 in base al predicato di intervallo utilizzando la colonna TransactionDate e l'intervallo di dati tra '20140614' e '20140618'.
Le statistiche per il passaggio dell'istogramma di questo intervallo sono le seguenti:
Secondo la formula, ho calcolato la cardinalità per la seguente query:
SELECT COUNT(1)
FROM [AdventureWorks2014].[Production].[TransactionHistory]
WHERE [TransactionDate] BETWEEN '20140615 00:00:00.000' AND '20140616 00:00:00.000'
Il calcolo è stato eseguito utilizzando il seguente codice:
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]
Dopo il calcolo, ho ottenuto i seguenti risultati:
Secondo la formula, risultava 150,5, ma l'ottimizzatore stima il predicato in 225,75 righe e se si modifica il bordo superiore del predicato in "20140617", l'ottimizzatore valuterà già 250.833 righe, mentre utilizzando la formula si ottiene solo 200.6666 righe.
Per favore dimmi, come valuta lo stimatore della cardinalità in questo caso, forse ho fatto un errore da qualche parte nella mia comprensione delle formule citate?