Ich habe versucht, Stichprobenschwellenwerte mit Statistikaktualisierungen auf SQL Server (2012) zu untersuchen, und dabei ein merkwürdiges Verhalten festgestellt. Grundsätzlich scheint die Anzahl der abgetasteten Zeilen unter Umständen zu variieren - auch bei gleichem Datensatz.
Ich führe diese Abfrage aus:
--Drop table if exists
IF (OBJECT_ID('dbo.Test')) IS NOT NULL DROP TABLE dbo.Test;
--Create Table for Testing
CREATE TABLE dbo.Test(Id INT IDENTITY(1,1) CONSTRAINT PK_Test PRIMARY KEY CLUSTERED, TextValue VARCHAR(20) NULL);
--Insert enough data so we have more than 8Mb (the threshold at which sampling kicks in)
INSERT INTO dbo.Test(TextValue)
SELECT TOP 1000000 'blahblahblah'
FROM sys.objects a, sys.objects b, sys.objects c, sys.objects d;
--Create Index on TextValue
CREATE INDEX IX_Test_TextValue ON dbo.Test(TextValue);
--Update Statistics without specifying how many rows to sample
UPDATE STATISTICS dbo.Test IX_Test_TextValue;
--View the Statistics
DBCC SHOW_STATISTICS('dbo.Test', IX_Test_TextValue) WITH STAT_HEADER;
Wenn ich mir die Ausgabe von SHOW_STATISTICS ansehe, stelle ich fest, dass sich die Anzahl der erfassten Zeilen bei jeder vollständigen Ausführung ändert (dh, die Tabelle wird gelöscht, neu erstellt und neu gefüllt).
Beispielsweise:
Zeilen abgetastet
- 318618
- 319240
- 324198
- 314154
Ich habe erwartet, dass diese Zahl jedes Mal dieselbe ist, wenn die Tabelle identisch ist. Übrigens bekomme ich dieses Verhalten nicht, wenn ich nur die Daten lösche und sie erneut einfüge.
Es ist keine kritische Frage, aber ich würde gerne verstehen, was los ist.
quelle
318618 = 1142*279
,319240 = 1144*279 + 64
,324198=1162*279
Und314154=1126
so ist die Varianz der Anzahl der Seiten , abgetastet.Antworten:
Hintergrund
Daten für das Statistikobjekt werden mit einer Anweisung der Form gesammelt:
Sie können diese Anweisung mit Extended Events oder Profiler (
SP:StmtCompleted
) sammeln .Abfragen zur Generierung von Statistiken greifen häufig auf die Basistabelle zu (anstatt auf einen nicht gruppierten Index), um das Clustering von Werten zu vermeiden, das normalerweise auf nicht gruppierten Indexseiten auftritt.
Die Anzahl der abgetasteten Zeilen hängt von der Anzahl der zum Abtasten ausgewählten ganzen Seiten ab. Jede Seite der Tabelle ist entweder ausgewählt oder nicht. Alle Zeilen auf ausgewählten Seiten tragen zur Statistik bei.
Zufällige Zahlen
SQL Server verwendet einen Zufallszahlengenerator, um zu entscheiden, ob eine Seite qualifiziert ist oder nicht. Der in diesem Fall verwendete Generator ist der Lehmer-Zufallszahlengenerator mit folgenden Parameterwerten:
Der Wert von wird berechnet als die Summe von:
Xseed
Der niedrige ganzzahlige Teil der (
bigint
) Basistabelle istpartition_id
zDer in der
REPEATABLE
Klausel angegebene WertUPDATE STATISTICS
ist derREPEATABLE
Wert 1.m_randomSeed
Element der internen Debugging-Informationen der Zugriffsmethode angezeigt, die in Ausführungsplänen angezeigt werden, wenn beispielsweise das Ablaufverfolgungsflag 8666 aktiviert ist<Field FieldName="m_randomSeed" FieldValue="1" />
Für SQL Server 2012 erfolgt diese Berechnung in
sqlmin!UnOrderPageScanner::StartScan
:Dabei
[rcx+30h]
enthält memory at die niedrigen 32 Bits der Partitions-ID und memory at[rcx+2Ch]
den verwendetenREPEATABLE
Wert.Der Zufallszahlengenerator wird später in derselben Methode initialisiert
sqlmin!RandomNumGenerator::Init
, wobei die Anweisung aufgerufen wird:... multipliziert den
41A7
Startwert mit dem Hexadezimalwert (16807 Dezimal = 7 5 ), wie in der obigen Gleichung gezeigt.Spätere Zufallszahlen (für einzelne Seiten) werden mit dem gleichen Basiscode wie in generiert
sqlmin!UnOrderPageScanner::SetupSubScanner
.StatMan
Für die
StatMan
oben gezeigte Beispielabfrage werden dieselben Seiten wie für die T-SQL-Anweisung gesammelt:Dies entspricht der Ausgabe von:
Edge-Fall
Eine Konsequenz der Verwendung des Zufallszahlengenerators von MINSTD Lehmer ist, dass die Startwerte Null und int.max nicht verwendet werden sollten, da dies dazu führt, dass der Algorithmus eine Folge von Nullen erzeugt (Auswahl jeder Seite).
Der Code erkennt Null und verwendet in diesem Fall einen Wert aus der Systemuhr als Startwert. Dies ist nicht der Fall, wenn der Startwert int.max (
0x7FFFFFFF
= 2 31 - 1) ist.Wir können dieses Szenario konstruieren, da der anfängliche
REPEATABLE
Startwert als die Summe der niedrigen 32 Bits der Partitions-ID und des Werts berechnet wird. DerREPEATABLE
Wert, der dazu führt, dass der Startwert int.max ist und daher jede Seite für die Stichprobe ausgewählt wird, ist:Das in ein vollständiges Beispiel umwandeln:
Dadurch wird jede Zeile auf jeder Seite ausgewählt, unabhängig davon, was in der
TABLESAMPLE
Klausel steht (sogar null Prozent).quelle
Das ist eine ausgezeichnete Frage! Ich fange mit dem an, was ich sicher weiß, und gehe dann zur Spekulation über. Viele Details dazu in meinem Blogbeitrag hier .
Sampled Stats-Updates werden
TABLESAMPLE
im Hintergrund verwendet. Es ist ziemlich einfach, online Dokumentation darüber zu finden. Ich bin jedoch der Meinung, dass es nicht allgemein bekannt ist, dass die von zurückgegebenen ZeilenTABLESAMPLE
teilweise vomhobt_id
Objekt abhängen . Wenn Sie das Objekt löschen und neu erstellen, erhalten Sie ein neues Objekt,hobt_id
sodass die durch Zufallsstichproben zurückgegebenen Zeilen unterschiedlich sind.Wenn Sie die Daten löschen und erneut einfügen, bleiben diese unverändert
hobt_id
. Solange die Daten auf dieselbe Weise auf der Festplatte angeordnet sind (ein Allokationsreihenfolge-Scan liefert dieselben Ergebnisse in derselben Reihenfolge), sollten sich die abgetasteten Daten nicht ändern.Sie können auch die Anzahl der untersuchten Zeilen ändern, indem Sie den Clustered-Index für die Tabelle neu erstellen. Beispielsweise:
Ich glaube, der Grund dafür ist, dass SQL Server den Clustered-Index anstelle des Nonclustered-Index durchsucht, wenn er Stichprobenstatistiken für einen Index sammelt. Ich denke auch, dass es einen verborgenen (für diejenigen von uns, die die verborgenen Statistik-Aktualisierungsabfragen verfolgen) Wert gibt,
REPEATABLE
der mit verwendet wirdTABLESAMPLE
. Ich habe nichts davon bewiesen, aber es erklärt, warum sich Ihr Histogramm und die untersuchten Zeilen bei einer Neuerstellung des Clustered-Index ändern.quelle
Ich habe dies in Inside Microsoft SQL Server 2008 gesehen: T-SQL-Abfrage von Itzik Ben-Gan und ich kann es nicht als Kommentar hinzufügen, daher poste ich es hier. Ich denke, es ist auch für andere interessant:
Siehe auch Sampling mit TABLESAMPLE by Roji. P. Thomas.
quelle