Freigeben über


Problembehandlung allgemeiner Leistungsprobleme mit Memory-Optimized Hashindizes

Dieses Thema konzentriert sich auf die Fehlerbehebung und die Umgehung häufiger Probleme mit Hashindizes.

Suche erfordert eine Teilmenge von Hash-Index-Schlüsselspalten

Ausstellen: Hashindizes erfordern Werte für alle Indexschlüsselspalten, um den Hashwert zu berechnen und die entsprechenden Zeilen in der Hashtabelle zu suchen. Wenn eine Abfrage daher Gleichheitsvorrädikate nur für eine Teilmenge der Indexschlüssel in der WHERE-Klausel enthält, kann SQL Server keine Indexsuche verwenden, um die Zeilen zu finden, die den Prädikaten in der WHERE-Klausel entsprechen.

Im Gegensatz dazu unterstützen sortierte Indizes wie die datenträgerbasierten nicht gruppierten Indizes und die speicheroptimierten nicht gruppierten Indizes die Indexsuche für eine Teilmenge der Indexschlüsselspalten, solange sie die führenden Spalten im Index sind.

Symptom: Dies führt zu einer Leistungsbeeinträchtigung, da SQL Server vollständige Tabellenscans anstelle einer Indexsuche ausführen muss, was in der Regel ein schnellerer Vorgang ist.

Problembehandlung: Neben der Leistungsbeeinträchtigung zeigt die Überprüfung der Abfragepläne einen Scan statt einer Indexsuche. Wenn die Abfrage relativ einfach ist, zeigt auch die Überprüfung des Abfragetexts und der Indexdefinition an, ob für die Suche eine Teilmenge der Indexschlüsselspalten erforderlich ist.

Betrachten Sie die folgende Tabelle und Abfrage:

CREATE TABLE [dbo].[od]  
(  
     o_id INT NOT NULL,  
     od_id INT NOT NULL,  
     p_id INT NOT NULL,  
     CONSTRAINT PK_od PRIMARY KEY NONCLUSTERED HASH (o_id, od_id) WITH (BUCKET_COUNT = 10000)  
)  
WITH (MEMORY_OPTIMIZED = ON)  
  
 SELECT p_id  
 FROM dbo.od  
 WHERE o_id=1  

Die Tabelle enthält einen Hashindex für die beiden Spalten (o_id, od_id), während die Abfrage über ein Gleichheits-Prädikat (o_id) verfügt. Da die Abfrage Gleichheitsvorsätze nur für eine Teilmenge der Indexschlüsselspalten aufweist, kann SQL Server keinen Indexsuche-Vorgang mit PK_od ausführen; Stattdessen muss SQL Server auf eine vollständige Indexüberprüfung zurückgesetzt werden.

Problemumgehungen: Es gibt eine Reihe möglicher Problemumgehungen. Beispiel:

  • Erstellen Sie den Index als Typ "nicht-geclustert" anstelle eines "nicht-geclusterten Hashs" neu. Der speicheroptimierte, nicht gruppierte Index wird sortiert, sodass SQL Server eine Indexsuche für die führenden Indexschlüsselspalten ausführen kann. Die resultierende Primärschlüsseldefinition für das Beispiel wäre constraint PK_od primary key nonclustered.

  • Ändern Sie den aktuellen Indexschlüssel so, dass er den Spalten in der WHERE-Klausel entspricht.

  • Fügen Sie einen neuen Hashindex hinzu, der mit den Spalten in der WHERE-Klausel der Abfrage übereinstimmt. Im Beispiel würde die resultierende Tabellendefinition wie folgt aussehen:

    CREATE TABLE dbo.od  
     ( o_id INT NOT NULL,  
     od_id INT NOT NULL,  
     p_id INT NOT NULL,  
    
     CONSTRAINT PK_od PRIMARY KEY   
     NONCLUSTERED HASH (o_id,od_id) WITH (BUCKET_COUNT=10000),  
    
     INDEX ix_o_id NONCLUSTERED HASH (o_id) WITH (BUCKET_COUNT=10000)  
    
     ) WITH (MEMORY_OPTIMIZED=ON)  
    

Beachten Sie, dass ein speicheroptimierter Hashindex nicht optimal ausgeführt wird, wenn viele doppelte Zeilen für einen bestimmten Indexschlüsselwert vorhanden sind: Wenn die Anzahl eindeutiger Werte für die Spalte o_id viel kleiner als die Anzahl der Zeilen in der Tabelle ist, wäre es nicht optimal, einen Index hinzuzufügen (o_id); Stattdessen wäre das Ändern des Indextyps PK_od von Hash zu nicht gruppiert die bessere Lösung. Weitere Informationen finden Sie unter Bestimmen der richtigen Bucketanzahl für Hashindizes.

Siehe auch

Indizes für Memory-Optimized Tabellen