Suche…


Einführung

Indizes sind eine Datenstruktur, die Zeiger auf den Inhalt einer Tabelle enthält, die in einer bestimmten Reihenfolge angeordnet ist, um die Datenbank bei der Optimierung von Abfragen zu unterstützen. Sie ähneln dem Buchindex, bei dem die Seiten (Tabellenzeilen) anhand ihrer Seitennummer indiziert werden.

Es gibt verschiedene Arten von Indizes, die für eine Tabelle erstellt werden können. Wenn für die in der WHERE-Klausel, JOIN-Klausel oder ORDER BY-Klausel einer Abfrage verwendeten Spalten ein Index vorhanden ist, kann die Abfrageleistung erheblich verbessert werden.

Bemerkungen

Indizes sind eine Möglichkeit, Leseanfragen zu beschleunigen, indem die Zeilen einer Tabelle nach einer Spalte sortiert werden.

Die Auswirkungen eines Index sind für kleine Datenbanken wie im Beispiel nicht erkennbar. Wenn jedoch eine große Anzahl von Zeilen vorhanden ist, kann dies die Leistung erheblich verbessern. Anstatt jede Zeile der Tabelle zu überprüfen, kann der Server eine binäre Suche nach dem Index durchführen.

Der Kompromiss beim Erstellen eines Indexes ist die Schreibgeschwindigkeit und die Datenbankgröße. Das Speichern des Index benötigt Platz. Jedes Mal, wenn ein INSERT ausgeführt wird oder die Spalte aktualisiert wird, muss der Index aktualisiert werden. Dies ist zwar nicht so teuer wie das Durchsuchen der gesamten Tabelle in einer SELECT-Abfrage, ist aber dennoch zu beachten.

Index erstellen

CREATE INDEX ix_cars_employee_id ON Cars (EmployeeId);

Dadurch wird ein Index für die Spalte EmployeeId in der Tabelle Cars erstellt . Dieser Index verbessert die Geschwindigkeit von Abfragen, die den Server auffordern, nach Werten in EmployeeId zu sortieren oder auszuwählen, z. B. die folgenden:

SELECT * FROM Cars WHERE EmployeeId = 1

Der Index kann wie im Folgenden mehr als eine Spalte enthalten.

CREATE INDEX ix_cars_e_c_o_ids ON Cars (EmployeeId, CarId, OwnerId);

In diesem Fall wäre der Index für Abfragen hilfreich, die nach allen enthaltenen Spalten sortieren oder auswählen, wenn der Satz von Bedingungen auf dieselbe Weise angeordnet ist. Das bedeutet, dass beim Abrufen der Daten die Zeilen abgerufen werden können, die mithilfe des Index abgerufen werden sollen, anstatt die vollständige Tabelle zu durchsuchen.

Im folgenden Fall würde beispielsweise der zweite Index verwendet.

SELECT * FROM Cars WHERE EmployeeId = 1 Order by CarId DESC

Wenn sich die Reihenfolge unterscheidet, hat der Index jedoch nicht die gleichen Vorteile wie im Folgenden.

SELECT * FROM Cars WHERE OwnerId = 17 Order by CarId DESC

Der Index ist nicht so hilfreich, da die Datenbank den gesamten Index über alle Werte von EmployeeId und CarID abrufen muss, um herauszufinden, welche Elemente OwnerId = 17 .

(Der Index kann weiterhin verwendet werden; der Abfrageoptimierer kann jedoch feststellen, dass das Abrufen des Indexes und das Filtern nach OwnerId und das Abrufen nur der benötigten Zeilen schneller ist als das Abrufen der vollständigen Tabelle, insbesondere wenn die Tabelle groß ist.)

Gruppierte, eindeutige und sortierte Indizes

Indizes können mehrere Merkmale aufweisen, die entweder beim Erstellen oder durch Ändern vorhandener Indizes festgelegt werden können.

CREATE CLUSTERED INDEX ix_clust_employee_id ON Employees(EmployeeId, Email);  

Die obige SQL-Anweisung erstellt einen neuen Clustered-Index für Mitarbeiter. Clustered-Indizes sind Indizes, die die tatsächliche Struktur der Tabelle bestimmen. Die Tabelle selbst wird nach der Indexstruktur sortiert. Das heißt, es kann höchstens einen Clustered-Index für eine Tabelle geben. Wenn für die Tabelle bereits ein gruppierter Index vorhanden ist, schlägt die obige Anweisung fehl. (Tabellen ohne Clustered-Indizes werden auch als Heap-Speicher bezeichnet.)

CREATE UNIQUE INDEX uq_customers_email ON Customers(Email);

Dadurch wird ein eindeutiger Index für die Spalte E-Mail in der Tabelle Customers erstellt . Dieser Index sowie die Beschleunigung von Abfragen wie ein normaler Index erzwingen auch, dass jede E-Mail-Adresse in dieser Spalte eindeutig ist. Wenn eine Zeile mit einem nicht eindeutigen E - Mail- Wert eingefügt oder aktualisiert wird, schlägt das Einfügen oder Aktualisieren standardmäßig fehl.

CREATE UNIQUE INDEX ix_eid_desc ON Customers(EmployeeID);

Dadurch wird ein Index für Kunden erstellt, der auch eine Tabellenbeschränkung erstellt, wonach die EmployeeID eindeutig sein muss. (Dies schlägt fehl, wenn die Spalte derzeit nicht eindeutig ist - in diesem Fall, wenn Mitarbeiter eine ID gemeinsam nutzen.)

CREATE INDEX ix_eid_desc ON Customers(EmployeeID Desc);

Dadurch wird ein Index erstellt, der in absteigender Reihenfolge sortiert ist. Standardmäßig sind Indizes (zumindest im MSSQL-Server) aufsteigend, dies kann jedoch geändert werden.

Einfügen mit einem eindeutigen Index

UPDATE Customers SET Email = "[email protected]" WHERE id = 1;

Dies schlägt fehl, wenn für die E-Mail- Spalte von Kunden ein eindeutiger Index festgelegt ist. Für diesen Fall kann jedoch ein alternatives Verhalten definiert werden:

UPDATE Customers SET Email = "[email protected]" WHERE id = 1 ON DUPLICATE KEY; 

SAP ASE: Index löschen

Dieser Befehl löscht den Index in der Tabelle. Es funktioniert auf einem SAP ASE Server.

Syntax:

DROP INDEX [table name].[index name]

Beispiel:

DROP INDEX Cars.index_1

Sortierter Index

Wenn Sie einen Index verwenden, der so sortiert ist, wie Sie ihn abrufen würden, führt die SELECT Anweisung beim Abrufen keine zusätzliche Sortierung durch.

CREATE INDEX ix_scoreboard_score ON scoreboard (score DESC);

Wenn Sie die Abfrage ausführen

SELECT * FROM scoreboard ORDER BY score DESC;

Das Datenbanksystem führt keine zusätzliche Sortierung durch, da es in dieser Reihenfolge eine Indexsuche durchführen kann.

Einen Index löschen oder ihn deaktivieren und neu erstellen

DROP INDEX ix_cars_employee_id ON Cars;  

Wir können den Befehl DROP , um unseren Index zu löschen. In diesem Beispiel werden wir DROP den Index ix_cars_employee_id auf dem Tisch Autos genannt.

Dadurch wird der Index vollständig gelöscht. Wenn der Index in einem Cluster zusammengefasst ist, wird das Clustering entfernt. Es kann nicht neu erstellt werden, ohne den Index neu zu erstellen, was langsam und rechenintensiv sein kann. Alternativ kann der Index deaktiviert werden:

ALTER INDEX ix_cars_employee_id ON Cars DISABLE; 

Dadurch kann die Tabelle die Struktur zusammen mit den Metadaten zum Index beibehalten.

Kritisch bleibt dabei die Indexstatistik erhalten, so dass die Änderung leicht ausgewertet werden kann. Bei Bedarf kann der Index später erneut erstellt werden, anstatt ihn vollständig neu zu erstellen.

ALTER INDEX ix_cars_employee_id ON Cars REBUILD;

Eindeutiger Index, der NULL erlaubt

CREATE UNIQUE INDEX idx_license_id 
   ON Person(DrivingLicenseID) WHERE DrivingLicenseID IS NOT NULL
GO

Dieses Schema ermöglicht eine 0..1-Beziehung - Personen können keinen oder einen Führerschein haben und jeder Führerschein kann nur einer Person gehören

Index neu erstellen

Im Laufe der Zeit können B-Tree-Indizes aufgrund der Aktualisierung / Löschung / Einfügung von Daten fragmentiert werden. In der SQLServer-Terminologie können wir interne (Indexseite, die halb leer ist) und extern (logische Seitenreihenfolge entspricht nicht der physischen Reihenfolge) haben. Die Neuerstellung des Index ist dem Löschen und Neuerstellen des Index sehr ähnlich.

Wir können einen Index mit neu erstellen

ALTER INDEX index_name REBUILD; 

Standardmäßig ist der Index für die Neuerstellung ein Offline-Vorgang, durch den die Tabelle gesperrt und DML dagegen verhindert wird. In vielen RDBMS ist jedoch eine Online-Wiederherstellung möglich. Einige DB-Anbieter bieten auch Alternativen zur REORGANIZE von Indizes an, wie z. B. REORGANIZE (SQLServer) oder COALESCE / SHRINK SPACE (Oracle).

Clustered-Index

Bei Verwendung eines Clustered-Index werden die Zeilen der Tabelle nach der Spalte sortiert, auf die der Clustered-Index angewendet wird. Daher kann es nur einen Clusterindex für die Tabelle geben, da Sie die Tabelle nicht nach zwei verschiedenen Spalten sortieren können.

Im Allgemeinen ist es am besten, einen Clustered-Index zu verwenden, wenn Lesevorgänge für große Datentabellen ausgeführt werden. Der Vorteil des Clustered-Index liegt beim Schreiben in eine Tabelle, und Daten müssen neu organisiert (sortiert) werden.

Ein Beispiel zum Erstellen eines gruppierten Index für eine Tabelle Employees in der Spalte Employee_Surname:

CREATE CLUSTERED INDEX ix_employees_name ON Employees(Employee_Surname);  

Nicht gruppierter Index

Nicht gruppierte Indizes werden getrennt von der Tabelle gespeichert. Jeder Index in dieser Struktur enthält einen Zeiger auf die Zeile in der Tabelle, die er darstellt.

Diese Zeiger werden Zeilenlokatoren genannt. Die Struktur des Zeilenlokators hängt davon ab, ob die Datenseiten in einem Heap oder in einer Clustertabelle gespeichert sind. Bei einem Heap ist ein Zeilenlokator ein Zeiger auf die Zeile. Bei einer gruppierten Tabelle ist der Zeilenlokator der gruppierte Indexschlüssel.

Ein Beispiel zum Erstellen eines nicht gruppierten Index für die Tabelle Employees und die Spalte Employee_Surname:

CREATE NONCLUSTERED INDEX ix_employees_name ON Employees(Employee_Surname);  

Es können mehrere nicht gruppierte Indizes für die Tabelle vorhanden sein. Die Leseoperationen sind bei nicht gruppierten Indizes im Allgemeinen langsamer als bei gruppierten Indizes, da Sie zuerst zum Index und dann zur Tabelle gehen müssen. Es gibt jedoch keine Einschränkungen bei Schreibvorgängen.

Teilweiser oder gefilterter Index

SQL Server und SQLite ermöglichen das Erstellen von Indizes, die nicht nur eine Teilmenge von Spalten enthalten, sondern auch eine Teilmenge von Zeilen.

Betrachten Sie eine konstant wachsende Anzahl von Bestellungen, wobei order_state_id gleich beendete (2) ist, und eine stabile Anzahl von Bestellungen, wobei order_state_id equal gestartet ist (1).

Wenn Ihr Unternehmen Fragen wie diese verwendet:

SELECT id, comment
  FROM orders
 WHERE order_state_id =  1
   AND product_id = @some_value;

Mit der teilweisen Indizierung können Sie den Index einschränken, einschließlich nur der noch nicht abgeschlossenen Aufträge:

CREATE INDEX Started_Orders
          ON orders(product_id)
       WHERE order_state_id = 1;

Dieser Index ist kleiner als ein ungefilterter Index, wodurch Platz gespart und die Aktualisierungskosten des Index reduziert werden.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow