Clustered Table Scan wegen "SELECT *"

7

Ich habe eine RecordsTabelle mit über 100 Spalten und sehr vielen Zeilen und einen nicht gruppierten Index für 5 Felder basierend auf meinen Zugriffspfaden:

CREATE NONCLUSTERED INDEX [IX_Records_CustomerID]
ON [dbo].[Records] (
    [CustomerID] ASC, -- int
    [IsInvalid] ASC, -- int
    [IsProcessed] ASC, -- bit
    [IsRejected] ASC, -- bit
    [RecordName] ASC, -- varchar(12)
;

Die 5 Felder enthalten nicht den Primärschlüssel RecordID, der die Spalte im Clustered-Index darstellt.

Hier ist meine schlecht funktionierende Abfrage:

SELECT * FROM Records WHERE CustomerID IN (181, 283, 505)

Der Ausführungsplan zeigt, dass er einen Clustered Index Scan durchführt. Ich verstehe, dass ich Spalten auswähle, die nicht im Index enthalten sind. In Management Studio ändere ich die Abfrage in:

SELECT CustomerID, IsInvalid, IsProcessed, IsRejected, RecordName FROM Records 
    WHERE CustomerID IN (181, 283, 505)

Der Ausführungsplan zeigt eine Indexsuche an, und die Ausführungszeit für Abfragen sinkt von 44 Sekunden auf 2 Sekunden. Es fehlt mir jedoch die Freiheit in der Anwendung, die *nur durch die Spalten zu ersetzen, die ich benötige und in meinen Index aufgenommen habe.

Gibt es einen Weg um den Clustered-Index-Scan herum, wenn ich gesperrt bin SELECT *?

Chris Schiffhauer
quelle
Das ist beabsichtigt. Es ist billiger, die Tabelle nach allen Feldern zu durchsuchen, als zwei Operationen auszuführen, eine im Index und eine in der Tabelle.
Max Vernon
3
Wenn Sie Wert auf Leistung legen, ändern Sie die App. Oh, und "Performant" bedeutet "jemand, der in einem Stück auftritt, etc".
Max Vernon
1
Was ist in der IN (…)Unterabfrage?
Greenstone Walker
2
Können Sie als Problemumgehung eine Ansicht erstellen (mit nur den 5 Spalten, die Sie benötigen) und dann die App verwenden lassen SELECT * FROM that_view WHERE CustomerID IN (...);?
Ypercubeᵀᴹ
1
@ MaxVernon Danke! "Performant" wird viel herumgeworfen, wo ich arbeite, jetzt weiß ich es! Ich habe meinen Wortlaut in der Frage überarbeitet.
Chris Schiffhauer

Antworten:

7

Wenn Sie Spalten in der Ausgabe benötigen, die nicht vom Index abgedeckt werden, muss der Optimierer eine Auswahl treffen:

  1. Führen Sie einen Tabellen- / Clustered-Index-Scan durch (daher sind alle Spalten vorhanden).
  2. Führen Sie eine Suche durch und führen Sie dann Suchvorgänge durch, um die nicht abgedeckten Spalten abzurufen

Welche Art und Weise gewählt wird, hängt von einer Vielzahl von Faktoren ab, einschließlich der Enge des Index, der Anzahl der Zeilen, die mit dem Prädikat übereinstimmen usw. Sie können eine Suche mit dem FORCESEEKHinweis erzwingen , aber ich vermute, dass die gleiche oder eine schlechtere Leistung erzielt wird als Der Scan, den SQL Server in Ihrem Fall ausgewählt hat.

Einige Optionen:

  1. Ändern Sie die App, um eine ordnungsgemäße Abfrage auszuführen. Ich habe dies aus einem bestimmten Grund zuerst aufgelistet .
  2. Erstellen Sie eine Ansicht, in der nur die Spalten ausgewählt werden, die Sie benötigen:

    CREATE VIEW dbo.myview
    WITH SCHEMABINDING
    AS
      SELECT col1, col2, col3 FROM dbo.tablename;

    Anschließend können Sie die App in SELECT *dieser Ansicht ändern . Oder Sie können noch kreativer werden und die ursprüngliche Tabelle umbenennen und den Namen dieser Ansicht in den Namen der Tabelle ändern. Offensichtlich die Veränderung brechen; mit Vorsicht fortfahren.

  3. Fügen Sie alle anderen Spalten zum Schlüssel oder zur INCLUDEListe für den Index hinzu. Wenn dies fest codierte Werte sind und immer die verwendeten, können Sie einen gefilterten Index in Betracht ziehen.

Aaron Bertrand
quelle
2
Vielen Dank und @MaxVernon für die Betonung der Wichtigkeit der Änderung der Abfrage. Ich werde mich von meinen Kollegen einkaufen lassen und das möglich machen.
Chris Schiffhauer
0

Wenn Sie diese anderen Felder im Index haben, wird es nur noch schlimmer, wenn Sie immer select * verwenden. Versuchen Sie, einen Index nur für CustomerID zu erstellen. Das mag helfen, hängt jedoch von verschiedenen Faktoren ab, z. B. davon, wie viele IDs in der In-Liste enthalten sind und wie viele Zeilen pro Kunden-ID in der Tabelle enthalten sind.

James Z.
quelle