les statistiques sont à jour, mais l'estimation est incorrecte

12

Lorsque dbcc show_statistics ('Reports_Documents', PK_Reports_Documents)j'obtiens, j'obtiens le résultat suivant pour le rapport ID 18698:

entrez la description de l'image ici

Pour cette requête:

SELECT * 
FROM Reports_Documents 
WHERE ReportID = 18698 option (recompile)

J'obtiens un plan de requête qui effectue une recherche d'index cluster PK_Reports_Documentscomme prévu.

Mais ce qui me déroute, c'est la valeur incorrecte du nombre estimé de lignes:

entrez la description de l'image ici

Selon ceci :

Lorsque l'exemple de valeur de clause WHERE de requête est égal à une valeur d'histogramme RANGE_HI_KEY, SQL Server utilise la colonne EQ_ROWS dans l'histogramme pour déterminer le nombre de lignes égales à

C'est aussi ainsi que je m'attendrais à ce que ce soit, mais cela ne semble pas être le cas dans la vraie vie. J'ai également essayé d'autres RANGE_HI_KEYvaleurs présentes dans l'histogramme fourni par show_statisticset vécu les mêmes. Ce problème dans mon cas semble entraîner certaines requêtes à utiliser des plans d'exécution très peu optimaux entraînant un temps d'exécution de quelques minutes alors que je peux le faire fonctionner en 1 seconde avec un indice de requête.

Dans l'ensemble: quelqu'un peut-il m'expliquer pourquoi EQ_ROWSl'histogramme n'est pas utilisé pour le nombre estimé de lignes et d'où vient l'estimation incorrecte?

Un peu plus d'informations (peut-être utiles):

  • La création automatique de statistiques est activée et toutes les statistiques sont à jour.
  • La table interrogée compte environ 80 millions de lignes.
  • PK_Reports_Documentsest une combinaison PK composée de ReportID INTetDocumentID CHAR(8)

La requête semble charger un total de 5 objets statistiques différents, qui contiennent tous ReportID+ quelques autres colonnes de la table. Ils ont tous été mis à jour récemment. RANGE_HI_KEYdans le tableau ci-dessous est la valeur de la colonne supérieure la plus élevée de l'histogramme.

+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
|                                  name                                   | stats_id | auto_created | user_created | Leading column Type | RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS  | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
| PK_Reports_Documents                                                    |        1 |            0 |            0 | Stationary          |        18722 | 0          | 2228,526 |                   0 | 1              |
| _dta_index_Reports_Documents_42_1629248859__K1_K63_K14_K13_K22_K23_72_6 |       62 |            0 |            0 | Stationary          |        18698 | 0          | 2228,526 |                   0 | 1              |
| _dta_stat_1629248859_1_1_59                                             |       76 |            0 |            1 | Stationary          |        18686 | 50,56393   | 1        |                   0 | 13397,04       |
| _dta_stat_1629248859_1_22_14_18_12_6                                    |       95 |            0 |            1 | Stationary          |        18698 | 0          | 2228,526 |                   0 | 1              |
| _dta_stat_1629248859_1_7_14_4_23_62                                     |       96 |            0 |            1 | Stationary          |        18698 | 56,63327   | 21641,5  |                   0 | 14526,44       |
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+

sp_updatestats doit être exécuté tous les soirs pour mettre à jour les statistiques.

user1151923
la source

Réponses:

10

Il existe une solution simple à cela:

Supprimez toutes les _dta_...statistiques et cessez d'appliquer aveuglément les recommandations DTA.

Plus d'information

Le problème particulier était qu'il y avait plusieurs ensembles de statistiques pour la colonne en question. Les dtastatistiques supplémentaires ont été créées en échantillonnant les données (le comportement par défaut pour les statistiques non associées à un index).

Comme c'est souvent le cas avec les statistiques échantillonnées, les histogrammes résultants ne couvraient pas la gamme complète des données sous-jacentes. La requête dans la question s'est avérée choisir une valeur qui était en dehors de l'histogramme, résultant en une estimation sur 1 ligne.

Le comportement exact de l'optimiseur de requêtes lorsque plusieurs ensembles de statistiques existent pour la même colonne n'est pas entièrement documenté. Il a tendance à préférer les statistiques de «balayage complet» aux échantillons, mais il préfère également les statistiques plus récemment mises à jour aux anciennes.

Aaron Bertrand
la source
Cela fonctionne effectivement. Je n'ai cependant pas créé les _dta_statistiques, elles étaient là depuis que j'ai eu mon premier aperçu sur la DB. Je ne savais pas que l'utilisation des recommandations pouvait avoir de tels effets négatifs ...
user1151923