La formule d'estimation des lignes devient un peu maladroite lorsque le filtre est "supérieur à" ou "inférieur à", mais c'est un nombre auquel vous pouvez arriver.
Les nombres
En utilisant l'étape 193, voici les numéros pertinents:
RANGE_ROWS = 6624
EQ_ROWS = 16
AVG_RANGE_ROWS = 16.1956
RANGE_HI_KEY de l'étape précédente = 1999-10-13 10: 47: 38.550
RANGE_HI_KEY de l'étape actuelle = 1999-10-13 10: 51: 19.317
Valeur de la clause WHERE = 1999-10-13 10: 48: 38.550
La formule
1) Trouvez le ms entre les deux touches hi de gamme
SELECT DATEDIFF (ms, '1999-10-13 10:47:38.550', '1999-10-13 10:51:19.317')
Le résultat est de 220767 ms.
2) Ajustez le nombre de lignes
Nous devons trouver les lignes par milliseconde, mais avant de le faire, nous devons soustraire AVG_RANGE_ROWS de RANGE_ROWS:
6624 - 16,1956 = 6607,8044 rangées
3) Calculez les lignes par ms avec le nombre de lignes ajusté:
6607.8044 lignes / 220767 ms = 0,0299311 lignes par ms
4) Calculez le ms entre la valeur de la clause WHERE et l'étape courante RANGE_HI_KEY
SELECT DATEDIFF (ms, '1999-10-13 10:48:38.550', '1999-10-13 10:51:19.317')
Cela nous donne 160767 ms.
5) Calculez les lignes de cette étape en fonction des lignes par seconde:
0,0299311 lignes / ms * 160767 ms = 4811,9332 lignes
6) Rappelez-vous comment nous avons soustrait AVG_RANGE_ROWS plus tôt? Il est temps de les rajouter. Maintenant que nous avons fini de calculer les nombres liés aux lignes par seconde, nous pouvons également ajouter EQ_ROWS en toute sécurité:
4811.9332 + 16.1956 + 16 = 4844.1288
Arrondi, c'est notre estimation 4844.13.
Test de la formule
Je n'ai trouvé aucun article ou article de blog expliquant pourquoi AVG_RANGE_ROWS est soustrait avant le calcul des lignes par ms. Je suis en mesure de confirmer qu'ils sont pris en compte dans l'estimation, mais seulement à la dernière milliseconde - littéralement.
En utilisant la base de données WideWorldImporters , j'ai effectué des tests incrémentiels et trouvé la diminution des estimations de lignes linéaire jusqu'à la fin de l'étape, où 1x AVG_RANGE_ROWS est soudainement pris en compte.
Voici mon exemple de requête:
SELECT PickingCompletedWhen
FROM Sales.Orders
WHERE PickingCompletedWhen >= '2016-05-24 11:00:01.000000'
J'ai mis à jour les statistiques de PickingCompletedWhen, puis j'ai obtenu l'histogramme:
DBCC SHOW_STATISTICS([sales.orders], '_WA_Sys_0000000E_44CA3770')
Pour voir comment les lignes estimées diminuent à l'approche de la RANGE_HI_KEY, j'ai collecté des échantillons tout au long de l'étape. La diminution est linéaire, mais se comporte comme si un nombre de lignes égal à la valeur AVG_RANGE_ROWS ne faisait tout simplement pas partie de la tendance ... jusqu'à ce que vous atteigniez la RANGE_HI_KEY et soudainement, elles chutent comme une dette non recouvrée annulée. Vous pouvez le voir dans les exemples de données, en particulier dans le graphique.
Notez la baisse régulière des lignes jusqu'à ce que nous atteignions le RANGE_HI_KEY puis le BOOM que le dernier bloc AVG_RANGE_ROWS soit subitement soustrait. Il est également facile de repérer un graphique.
Pour résumer, le traitement étrange d'AVG_RANGE_ROWS rend le calcul des estimations de ligne plus complexe, mais vous pouvez toujours concilier ce que fait le CE.
Qu'en est-il de l'interruption exponentielle?
L'arrêt exponentiel est la méthode que le nouveau (à partir de SQL Server 2014) Cardinality Estimator utilise pour obtenir de meilleures estimations lors de l'utilisation de plusieurs statistiques sur une seule colonne. Étant donné que cette question concernait une seule statistique de colonne, elle n'implique pas la formule EB.