Aktualisiert ein Neuindex die Statistiken?

43

Ich habe in der vergangenen Woche den MS10775A-Kurs absolviert und eine Frage, die der Trainer nicht zuverlässig beantworten konnte, ist:

Aktualisiert ein Neuindex die Statistiken?

Wir fanden Diskussionen online, in denen wir sowohl darüber diskutierten, dass dies der Fall ist, als auch darüber, dass dies nicht der Fall ist.

Thor Erik
quelle
Es ist nützlich , zu beachten , dass eine REINDEXnicht aktualisiert Spaltenstatistiken als Nebeneffekt den Index wieder aufzubauen - Sie müssen nicht brauchen , die Statistiken zu aktualisieren , um. Die Daten in der Tabelle ändern sich nicht. Es sind die gleichen Daten, es ist nur a) die Position auf dem sich drehenden Plattenteller verschoben (wenn eine Seite neu organisiert wird) oder b) auf einer anderen Seite (im Fall eines Neuaufbaus). Also: ein Re-Index hat update (einige) Statistiken: Es gibt keine Notwendigkeit , es zu tun.
Ian Boyd

Antworten:

51

Beachten Sie Folgendes, wenn Sie sich um die Aktualisierung von Statistiken kümmern (kopiert aus Neuerstellung von Indizes vs. Aktualisierung von Statistiken (Benjamin Nevarez))

  1. Standardmäßig verwendet die UPDATE STATISTICSAnweisung nur eine Stichprobe von Datensätzen der Tabelle. Mit UPDATE STATISTICS WITH FULLSCANscannen Sie die gesamte Tabelle.

  2. Standardmäßig UPDATE STATISTICSaktualisiert die Anweisung sowohl die Index- als auch die Spaltenstatistik. Mit dieser COLUMNSOption werden nur die Spaltenstatistiken aktualisiert. Mit dieser INDEXOption werden nur die Indexstatistiken aktualisiert.

  3. Durch das Neuerstellen eines Index , beispielsweise mithilfe von, ALTER INDEX … REBUILDwerden auch die Indexstatistiken mit dem Äquivalent von using aktualisiert, WITH FULLSCAN sofern die Tabelle nicht partitioniert ist. In diesem Fall werden nur Stichproben der Statistiken erstellt (gilt für SQL Server 2012 und höher).

  4. Statistiken, die manuell mit erstellt wurden, CREATE STATISTICSwerden durch keine ALTER INDEX ... REBUILDOperation aktualisiert , einschließlich ALTER TABLE ... REBUILD. ALTER TABLE ... REBUILDAktualisiert die Statistiken für den Clustered-Index, wenn einer für die neu erstellte Tabelle definiert ist.

  5. Durch das Reorganisieren eines Index , beispielsweise mit, werden ALTER INDEX … REORGANIZEkeine Statistiken aktualisiert.

Die kurze Antwort lautet, dass Sie UPDATE STATISTICSzum Aktualisieren von Spaltenstatistiken verwenden müssen und dass bei einer Indexwiederherstellung nur die Indexstatistiken aktualisiert werden. Sie können mit der UPDATE STATISTICS (tablename) WITH FULLSCAN;Syntax eine Aktualisierung aller Statistiken für eine Tabelle erzwingen, einschließlich Indexstatistiken und manuell erstellter Statistiken .

Der folgende Code veranschaulicht die oben gekapselten Regeln:

Zunächst erstellen wir eine Tabelle mit einigen Spalten und einem Clustered-Index:

USE tempdb;

IF OBJECT_ID(N'dbo.SomeTable', N'U') IS NOT NULL
DROP TABLE dbo.SomeTable;

CREATE TABLE dbo.SomeTable
(
    rn int NOT NULL IDENTITY(1,1)
        CONSTRAINT pk
        PRIMARY KEY NONCLUSTERED
    , i int NOT NULL INDEX i 
    , d sysname NOT NULL
) ON [PRIMARY] WITH (DATA_COMPRESSION = NONE);

CREATE UNIQUE CLUSTERED INDEX cx ON dbo.SomeTable (i, d);

CREATE STATISTICS d ON dbo.SomeTable (d) WITH FULLSCAN;

INSERT INTO dbo.SomeTable (d, i)
SELECT c1.name, c1.id
FROM sys.syscolumns c1;

Diese Abfrage zeigt das Datum, an dem jedes Statistikobjekt zuletzt aktualisiert wurde:

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

Die Ergebnisse zeigen, dass noch keine Aktualisierungen stattgefunden haben. Dies ist korrekt, da wir gerade die Tabelle erstellt haben:

╔═══════════════╦═══════════╦═══════════╗
║ ObjectName ║ StatsName ║ StatsDate ║
╠═══════════════╬═══════════╬═══════════╣
║ dbo.SomeTable ║ cx ║ NULL ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ NULL ║
╚═══════════════╩═══════════╩═══════════╝

Lassen Sie uns die gesamte Tabelle neu erstellen und prüfen, ob die Statistiken aktualisiert werden:

ALTER TABLE dbo.SomeTable REBUILD;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗
║ ObjectName ║ StatsName ║ StatsDate ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ NULL ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

Die Ergebnisse zeigen, dass nur die Clustered-Index- Statistiken aktualisiert wurden.

Als nächstes führen wir eine diskrete UPDATE STATSOperation durch:

UPDATE STATISTICS dbo.SomeTable(d) WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

Wie Sie sehen, haben wir gerade die Statistiken in der dSpalte aktualisiert :

╔═══════════════╦═══════════╦═════════════════════ ════╗
║ ObjectName ║ StatsName ║ StatsDate ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.597 ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

Jetzt aktualisieren wir die Statistiken für die gesamte Tabelle:

UPDATE STATISTICS dbo.SomeTable WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗
║ ObjectName ║ StatsName ║ StatsDate ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.600 ║
║ dbo.SomeTable ║ i ║ 2018-09-17 14: 09: 13.600 ║
║ dbo.SomeTable ║ pk ║ 2018-09-17 14: 09: 13.603 ║
║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.607 ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

Wie Sie sehen, besteht die einzige Möglichkeit, sicherzustellen, dass alle Statistiken aktualisiert werden, darin, entweder die einzelnen manuell zu aktualisieren oder die gesamte Tabelle mit zu aktualisieren UPDATE STATISTICS (table);.

MicSim
quelle
@JeremyWeir - Wie Sie aus dem Beispielcode ersehen können, den ich gerade der obigen Frage hinzugefügt habe, werden nur die Statistiken aktualisiert, die entweder über eine ALTER INDEX ... REBUILDoder eine UPDATE STATISTICSAnweisung explizit aktualisiert wurden . Wenn die Tabelle selbst neu erstellt wird, werden nur die Clustered-Index-Statistiken aktualisiert. Zu Ihrer Information: Ein Primärschlüssel und ein Clustered-Index werden nicht unbedingt von demselben Indexobjekt unterstützt.
Max Vernon
5

Die Microsoft Docs-Seite für SQL Server-Statistiken enthält folgende Informationen :

Vorgänge wie das Neuerstellen, Defragmentieren oder Reorganisieren eines Index ändern die Datenverteilung nicht. Daher müssen Sie die Statistiken nicht aktualisieren, nachdem Sie die Vorgänge ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG oder ALTER INDEX REORGANIZE ausgeführt haben . Das Abfrageoptimierungsprogramm aktualisiert Statistiken, wenn Sie einen Index für eine Tabelle oder Ansicht mit ALTER INDEX REBUILD oder DBCC DBREINDEX neu erstellen. Diese Aktualisierung der Statistiken ist jedoch ein Nebeneffekt der Neuerstellung des Index. Das Abfrageoptimierungsprogramm aktualisiert Statistiken nach DBCC INDEXDEFRAG- oder ALTER INDEX REORGANIZE-Vorgängen nicht.

b Seite
quelle