Statistiken sind aktuell, aber die Schätzung ist falsch

12

Wenn ich dies tue, dbcc show_statistics ('Reports_Documents', PK_Reports_Documents)erhalte ich das folgende Ergebnis für die Berichts-ID 18698:

Bildbeschreibung hier eingeben

Für diese Abfrage:

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

Ich bekomme einen Abfrageplan, der ein Clustered Index Seek auf macht , PK_Reports_Documentswie erwartet.

Was mich jedoch verwirrt, ist der falsche Wert für die geschätzte Anzahl der Zeilen:

Bildbeschreibung hier eingeben

Nach dieser :

Wenn der Wert der WHERE-Klausel der Beispielabfrage einem Histogramm-RANGE_HI_KEY-Wert entspricht, verwendet SQL Server die Spalte EQ_ROWS im Histogramm, um die Anzahl der Zeilen zu bestimmen, die gleich sind

Dies ist auch so, wie ich es erwarten würde, aber es scheint im wirklichen Leben nicht der Fall zu sein. Ich habe auch einige andere RANGE_HI_KEYWerte ausprobiert , die in dem von bereitgestellten Histogramm vorhanden waren, show_statisticsund habe dasselbe erlebt. In meinem Fall scheint dieses Problem dazu zu führen, dass einige Abfragen sehr unoptimale Ausführungspläne verwenden, was zu einer Ausführungszeit von einigen Minuten führt, während ich es mit einem Abfragehinweis in 1 Sekunde ausführen kann.

Alles in allem: Kann mir jemand erklären, warum EQ_ROWSdas Histogramm nicht für die geschätzte Anzahl der Zeilen verwendet wird und woher die falsche Schätzung stammt?

Ein bisschen mehr (möglicherweise hilfreiche) Informationen:

  • Die automatische Erstellung von Statistiken ist aktiviert und alle Statistiken sind auf dem neuesten Stand.
  • Die abgefragte Tabelle enthält ungefähr 80 Millionen Zeilen.
  • PK_Reports_Documentsist eine Kombinations-PK bestehend aus ReportID INTundDocumentID CHAR(8)

Die Abfrage scheint insgesamt 5 verschiedene Statistikobjekte zu laden, die alle ReportID+ einige andere Spalten aus der Tabelle enthalten. Sie wurden alle frisch aktualisiert. RANGE_HI_KEYIn der folgenden Tabelle ist der höchste Wert der oberen Spalte im Histogramm angegeben.

+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
|                                  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 wird voraussichtlich jede Nacht ausgeführt, um die Statistiken zu aktualisieren.

user1151923
quelle

Antworten:

10

Hierfür gibt es eine einfache Lösung:

Löschen Sie alle _dta_...Statistiken und wenden Sie die DTA-Empfehlungen nicht mehr blind an.

Mehr Informationen

Das besondere Problem bestand darin, dass für die betreffende Spalte mehrere Statistiksätze vorhanden waren. Die zusätzlichen dtaStatistiken wurden durch Stichprobenerfassung der Daten erstellt (das Standardverhalten für Statistiken, die keinem Index zugeordnet sind).

Wie so oft bei Stichprobenstatistiken deckten die resultierenden Histogramme nicht den gesamten Bereich der unerlying-Daten ab. Bei der Abfrage in der Frage wurde ein Wert ausgewählt, der außerhalb des Histogramms lag, was zu einer einzeiligen Schätzung führte.

Das genaue Verhalten des Abfrageoptimierers bei mehreren Statistiksätzen für dieselbe Spalte ist nicht vollständig dokumentiert. In der Regel werden Statistiken mit vollständiger Überprüfung der Stichprobe vorgezogen, aber es werden auch Statistiken mit neueren Aktualisierungen den älteren vorgezogen.

Aaron Bertrand
quelle
Das funktioniert tatsächlich. Ich habe die _dta_Statistiken jedoch nicht erstellt , sie waren da, seit ich meinen ersten Blick auf die DB geworfen habe. Ich wusste nicht, dass die Verwendung der Empfehlungen solche nachteiligen Auswirkungen haben kann ...
user1151923