2016-08-10 3 views
1

Die Frage bezieht sich auf MS SQL Server 2008+.Index Suche nach geschätzten Zeilen

Mit Tabelle (sagen wir, 5-10M Reihen)

CREATE TABLE [Test].[Persons](
[PersonId] [int] NOT NULL, 
[FirstName] [varchar] (50) NOT NULL, 
[LastName] [varchar] (50) NOT NULL, 
[OtherNames] [varchar] (50) NULL, 
[BirthDate] [varchar] (10) NULL 
CONSTRAINT [PK_Persons] PRIMARY KEY CLUSTERED ([PersonId] ASC) 
) 

Mit Index

CREATE NONCLUSTERED INDEX [IX_Persons_LastName_FirstName] 
ON [Test].[Persons] ([LastName] ASC, [FirstName] ASC) 

Ausführen einfache Abfrage wie

SELECT [FirstName],[LastName],[BirthDate] 
FROM [Test].[Persons] WHERE [LastName] = 'Decker' 

Ich sehe, dass mit Index Seek Operator, wenn der Schlüssel nicht im Statistik-Histogr ist Genaue Werte, geschätzte Zeilen unterscheiden sich stark von tatsächlichen Zeilen.
Für einige bestimmte Schlüssel kann es etwa 15 geschätzte Zeilen vs 10k tatsächlichen Zeilen sein.
Scheint wie in diesem Fall "Geschätzte Zeilen" Wert wird direkt von AVG_RANGE_ROWS für entsprechende Intervall (d. H. Nächsten Histogramm Wert) genommen.

Ist es erwartetes Verhalten? Ich meine, weiß "SQL Server", dass der Wert nicht exakt ist und verwendet diese Tatsache bei der Berechnung der Abfragekosten, oder ist es ein mögliches falsches Abfrageplanproblem?

Versucht mit SQL2008R2, 2012, 2014 (alle mit OLD Cardinality Estimator) Soweit ich weiß, ändert neues CE Dinge nur, wenn es um mehrere Tabellen in der Abfrage geht. Es ist interessant zu versuchen, aber ich habe es noch nicht.

+0

Ich glaube, es liegt daran, dass die Statistiken Probe nur an, wie viele DECKER errät Sie haben wahrscheinlich - versuchen Sie einige häufige und seltene Namen und sehen Sie, ob es ein Muster gibt – Cato

+0

Versuchen Sie, UPDATE STATISTICS –

+0

@Tab Alleman Statistiken wurden mit FULLSCAN kurz vor der Abfrage Ausführung aktualisiert. – Marvin

Antwort

0

Ich habe an dieser Frage etwas gearbeitet und es klargestellt.

Kurze Antwort: Nun, Schande über mich. Genau so funktioniert Statistik. In meinem Fall würden zusätzliche gefilterte Statistiken gewinnen. Danke für die Kommentare, sie waren wirklich nützlich, um zu überprüfen.

Lange Antwort: Das "Problem" war in der Verteilung der Schlüssel über Daten. Ich hatte alle 200 Schritte im Histogramm ausgefüllt und konnte keine Informationen über exakte sehr häufige Werte mehr sammeln. Über mehr als 500k relativ seltene eindeutige Werte gab es offensichtlich (für mich jetzt) ​​Wirkung.

Ich habe ein einfaches Beispiel Skript, was zeigt ein ähnliches Verhalten gemacht:

CREATE TABLE [TestStatistics] (
[Id] [INT] IDENTITY (1,1) PRIMARY KEY, 
[Val] [INT] NOT NULL 
) 
GO 
--Insert 200k rows with ~60k distinct values 
insert into TestStatistics (Val) VALUES (CHECKSUM (newid())%30000) 
go 200000 
--Insert 100k rows with ~600 distinct values, that are multiples of 100 
insert into TestStatistics (Val) VALUES (CHECKSUM (newid())%300*100) 
GO 100000 

create nonclustered index IX_TestStatistics_Val on TestStatistics(Val ASC) 
GO 

So habe ich 300k insgesamt Zeilen mit ~ 60k verschiedene Werte eingesetzt, die eine Dichte von ~ 0,2 über der Tabelle bedeutet. Und ich habe "spezielle" 100k-Zeilen, die mit ~ 600 verschiedenen Werten gefüllt sind - Vielfache von 100. Das heißt, jede dieser Zeilen wird ~ 166 mal angetroffen. und Statistiken werden jetzt wie folgt aussehen:

Statistics

Nun, wenn ich alle 100 Multiple nehmen, die im Histogramm (zB 7500) nicht vorhanden ist, werde ich Schätzung für 4,5-5,5 Reihen erhalten und fast 166 tatsächliche Reihen. Geschätzter Wert ist wirklich nur der nächste AVG_RANGE_ROWS-Wert aus dem Histogramm (für 7500 - bei Val = 7800).

Nun, wenn ich ein paar zusätzliche Statistiken zu sammeln, wie

CREATE STATISTICS ST_TestStatistics_0_10000 
ON TestStatistics(Val) WHERE Val>=0 AND Val<10000 

Ich werde eine weitere Abfrage-Plan erhalten:

Query Plans