La formula per stimare le righe diventa un po 'sciocca quando il filtro è "maggiore di" o "minore di", ma è un numero a cui puoi arrivare.
I numeri
Usando il passo 193, ecco i numeri rilevanti:
RANGE_ROWS = 6624
EQ_ROWS = 16
AVG_RANGE_ROWS = 16.1956
RANGE_HI_KEY dal passaggio precedente = 1999-10-13 10: 47: 38.550
RANGE_HI_KEY dal passaggio corrente = 1999-10-13 10: 51: 19.317
Valore dalla clausola WHERE = 1999-10-13 10: 48: 38.550
La formula
1) Trova il ms tra i due tasti della gamma
SELECT DATEDIFF (ms, '1999-10-13 10:47:38.550', '1999-10-13 10:51:19.317')
Il risultato è 220767 ms.
2) Regola il numero di righe
Dobbiamo trovare le righe per millisecondo, ma prima di farlo, dobbiamo sottrarre AVG_RANGE_ROWS da RANGE_ROWS:
6624 - 16.1956 = 6607.8044 righe
3) Calcola le righe per ms con il numero corretto di righe:
6607.8044 righe / 220767 ms = .0299311 righe per ms
4) Calcola il ms tra il valore della clausola WHERE e il passaggio corrente RANGE_HI_KEY
SELECT DATEDIFF (ms, '1999-10-13 10:48:38.550', '1999-10-13 10:51:19.317')
Questo ci dà 160767 ms.
5) Calcola le righe in questo passaggio in base alle righe al secondo:
.0299311 righe / ms * 160767 ms = 4811.9332 righe
6) Ricordi come abbiamo sottratto AVG_RANGE_ROWS in precedenza? È ora di aggiungerli di nuovo. Ora che abbiamo finito di calcolare i numeri relativi alle righe al secondo, possiamo tranquillamente aggiungere anche EQ_ROWS:
4811.9332 + 16.1956 + 16 = 4844.1288
Arrotondato, questa è la nostra stima 4844.13.
Test della formula
Non sono riuscito a trovare articoli o post sul blog sul motivo per cui AVG_RANGE_ROWS viene sottratto prima che vengano calcolate le righe per ms. Sono stato in grado di confermare che sono stati contabilizzati nel preventivo, ma solo all'ultimo millisecondo - letteralmente.
Usando il database WideWorldImporter , ho fatto alcuni test incrementali e ho scoperto che la diminuzione delle stime delle righe era lineare fino alla fine del passaggio, dove improvvisamente viene contabilizzato 1x AVG_RANGE_ROWS.
Ecco la mia query di esempio:
SELECT PickingCompletedWhen
FROM Sales.Orders
WHERE PickingCompletedWhen >= '2016-05-24 11:00:01.000000'
Ho aggiornato le statistiche per PickingCompletedWhen, quindi ho ottenuto l'istogramma:
DBCC SHOW_STATISTICS([sales.orders], '_WA_Sys_0000000E_44CA3770')
Per vedere come diminuiscono le righe stimate mentre ci avviciniamo a RANGE_HI_KEY, ho raccolto campioni durante tutto il passaggio. La riduzione è lineare, ma si comporta come se un numero di righe pari al valore AVG_RANGE_ROWS non facesse parte del trend ... fino a quando non si preme RANGE_HI_KEY e all'improvviso cadono come un debito non riscosso cancellato. Puoi vederlo nei dati di esempio, specialmente nel grafico.
Notare il costante declino delle righe fino a quando non si preme RANGE_HI_KEY e quindi BOOM che l'ultimo blocco AVG_RANGE_ROWS viene sottratto all'improvviso. È anche facile individuarlo in un grafico.
Per riassumere, lo strano trattamento di AVG_RANGE_ROWS rende più complesso il calcolo delle stime delle righe, ma è sempre possibile riconciliare ciò che sta facendo il CE.
Che dire del backoff esponenziale?
Exponential Backoff è il metodo utilizzato dal nuovo Estimatore di cardinalità (a partire da SQL Server 2014) per ottenere stime migliori quando si utilizzano più statistiche a colonna singola. Poiché questa domanda riguardava una statistica a colonna singola, non implica la formula EB.