Warum ist die automatisch erstellte Statistik in dieser Spalte leer?

8

Die Info

Meine Frage bezieht sich auf eine mäßig große Tabelle (~ 40 GB Datenraum), die ein Heap ist
(leider darf ich von den Anwendungsbesitzern keinen Clustered-Index zur Tabelle hinzufügen).

Eine automatisch erstellte Statistik für eine Identitätsspalte ( ID) wurde erstellt, ist jedoch leer.

  • Statistiken automatisch erstellen und Statistiken automatisch aktualisieren sind aktiviert
  • In der Tabelle wurden Änderungen vorgenommen
  • Es gibt andere (automatisch erstellte) Statistiken, die aktualisiert werden
  • Es gibt eine andere Statistik in derselben Spalte, die von einem Index erstellt wurde (Duplikat).
  • Build: 12.0.5546

Die doppelte Statistik wird aktualisiert: Geben Sie hier die Bildbeschreibung ein

Die eigentliche Frage

Nach meinem Verständnis könnten alle Statistiken verwendet und Änderungen verfolgt werden, selbst wenn zwei Statistiken zu genau denselben Spalten (Duplikaten) vorhanden sind. Warum bleibt diese Statistik also leer?

Statistik Info

Geben Sie hier die Bildbeschreibung ein

DB stat info

Geben Sie hier die Bildbeschreibung ein

Tischgröße

Geben Sie hier die Bildbeschreibung ein

Spalteninformationen, in denen die Statistik erstellt wird

Geben Sie hier die Bildbeschreibung ein

[ID] [int] IDENTITY(1,1) NOT NULL

Identitätsspalte

select * from sys.stats  
where name like '%_WA_Sys_0000000A_6B7099F3%';

Geben Sie hier die Bildbeschreibung ein Automatisch erstellt

Informationen zu einer anderen Statistik erhalten

select * From sys.dm_db_stats_properties (1802541555, 3)  

Geben Sie hier die Bildbeschreibung ein

Im Vergleich zu meiner leeren Statistik:

Geben Sie hier die Bildbeschreibung ein

Statistik + Histogramm aus "Skripte generieren":

/****** Object:  Statistic [_WA_Sys_0000000A_6B7099F3]    Script Date: 2/1/2019 10:18:19 AM ******/

    CREATE STATISTICS [_WA_Sys_0000000A_6B7099F3] ON [dbo].[table]([ID]) WITH STATS_STREAM = 0x01000000010000000000000000000000EC03686B0000000040000000000000000000000000000000380348063800000004000A00000000000000000000000000

Beim Erstellen einer Kopie der Statistiken befinden sich keine Daten darin

CREATE STATISTICS [_WA_Sys_0000000A_6B7099F3_TEST] ON [dbo].[table]([ID]) WITH STATS_STREAM = 0x01000000010000000000000000000000EC03686B0000000040000000000000000000000000000000380348063800000004000A00000000000000000000000000

Geben Sie hier die Bildbeschreibung ein

Wenn die Statistik manuell aktualisiert wird, werden sie aktualisiert.

UPDATE STATISTICS [dbo].[Table]([_WA_Sys_0000000A_6B7099F3_TEST])

Geben Sie hier die Bildbeschreibung ein

Randi Vertongen
quelle

Antworten:

9

Ich konnte dies sowohl mit einer leeren Statistik als auch mit einer aufgefüllten Statistik reproduzieren. Ich habe dafür gesorgt, dass eine automatische Statistik für eine leere Tabelle erstellt wird, und der Index wurde später erstellt:

IF OBJECT_ID(N'dbo.Heap', N'U') IS NOT NULL
BEGIN
    DROP TABLE dbo.Heap;
END;
GO
CREATE TABLE dbo.Heap 
(
    id integer NOT NULL IDENTITY,
    val integer NOT NULL,
);
GO
-- Add 1000 rows
INSERT dbo.Heap
    WITH (TABLOCKX)
    (val)
SELECT
    SV.number
FROM master.dbo.spt_values AS SV
WHERE
    SV.[type] = N'P'
    AND SV.number BETWEEN 1 AND 1000;
GO
SELECT COUNT_BIG(*) 
FROM dbo.Heap AS H
JOIN dbo.Heap AS H2
    ON H2.id = H.id
WHERE H.id > 0
AND H2.id > 0;
GO
-- Empty table
TRUNCATE TABLE dbo.Heap;
GO
-- Repeat exact same query (RT = 500 + 0.2 * 1000 = 700)
GO
SELECT COUNT_BIG(*) 
FROM dbo.Heap AS H
JOIN dbo.Heap AS H2
    ON H2.id = H.id
WHERE H.id > 0
AND H2.id > 0;
GO
-- Add 1000 rows
INSERT dbo.Heap
    WITH (TABLOCKX)
    (val)
SELECT
    SV.number
FROM master.dbo.spt_values AS SV
WHERE
    SV.[type] = N'P'
    AND SV.number BETWEEN 1 AND 1000;
GO
-- Add index
ALTER TABLE dbo.Heap ADD 
    CONSTRAINT [PK dbo.Heap id]
    PRIMARY KEY NONCLUSTERED (id);
GO
SELECT
    S.[name],
    S.auto_created,
    DDSP.stats_id,
    DDSP.last_updated,
    DDSP.[rows],
    DDSP.rows_sampled,
    DDSP.steps,
    DDSP.unfiltered_rows,
    DDSP.modification_counter
FROM sys.stats AS S
CROSS APPLY sys.dm_db_stats_properties(S.[object_id], S.stats_id) AS DDSP
WHERE 
    S.[object_id] = OBJECT_ID(N'dbo.Heap', N'U');

Ausgabe

Ich habe festgestellt, dass Änderungen weiterhin auf allen nicht leeren Duplikaten genau verfolgt werden, aber nur eine Statistik automatisch aktualisiert wird (unabhängig von der asynchronen Einstellung).

Automatische Statistikaktualisierungen werden nur durchgeführt, wenn das Abfrageoptimierungsprogramm eine bestimmte Statistik benötigt und feststellt, dass diese veraltet ist (eine auf die Optimalität bezogene Neukompilierung).

Das Optimierungsprogramm wählt aus doppelten Statistiken aus, wie im Dokument Plan-Caching und Neukompilierungen in SQL Server 2012 beschrieben:

Ein Problem, das nicht direkt mit dem Thema dieses Dokuments zusammenhängt, lautet: Wie entscheidet das Abfrageoptimierungsprogramm bei mehreren Statistiken für denselben Spaltensatz in derselben Reihenfolge, welche während der Abfrageoptimierung geladen werden sollen? Die Antwort ist nicht einfach, aber das Abfrageoptimierungsprogramm verwendet folgende Richtlinien: Bevorzugen Sie aktuelle Statistiken gegenüber älteren Statistiken. Bevorzugen Sie Statistiken, die mit der FULLSCANOption berechnet wurden, gegenüber Statistiken , die mit Stichproben berechnet wurden. und so weiter.

Der Punkt ist, dass der Optimierer eine der verfügbaren doppelten Statistiken auswählt (die "beste") und dass diese automatisch aktualisiert wird, wenn sich herausstellt, dass sie veraltet ist.

Ich glaube, dies ist eine Verhaltensänderung gegenüber älteren Versionen - oder zumindest die Dokumentation legt nahe, dass alle veralteten Statistiken für ein Objekt im Rahmen dieses Prozesses aktualisiert werden, aber ich habe keine Ahnung, wann sich dies geändert hat. Es war sicherlich nach August 2013, als Matt Bowler Duplicate Statistics veröffentlichte , das ein praktisches AdventureWorks-basiertes Repo enthält. Dieses Skript führt jetzt dazu, dass nur eines der Statistikobjekte aktualisiert wird, während dies zu der Zeit beide waren.

Die obige Erklärung entspricht allen Verhaltensweisen, die ich beim Versuch, Ihr Szenario zu reproduzieren, beobachtet habe, aber ich bezweifle, dass es irgendwo explizit dokumentiert ist. Dies scheint eine sinnvolle Optimierung zu sein, da es wenig sinnvoll ist, Duplikate vollständig zu aktualisieren.

Dies ist wahrscheinlich alles auf einer Detailebene, die unter der liegt, die Microsoft unterstützen möchte. Dies bedeutet auch, dass es sich ohne vorherige Ankündigung ändern kann.

Paul White 9
quelle