Sie müssen für jede where-Bedingung und für jede join...on-Bedingung nachschlagen. Beide funktionieren gleich.
Angenommen, wir schreiben
select name
from customer
where customerid=37;
Irgendwie muss das DBMS den oder die Datensätze mit customerid=37 finden. Wenn es keinen Index gibt, ist die einzige Möglichkeit, dies zu tun, jeden Datensatz in der Tabelle zu lesen und die Kunden-ID mit 37 zu vergleichen. Selbst wenn es eine findet, hat es keine Möglichkeit zu wissen, dass es nur eine gibt, also muss es weiter suchen andere.
Wenn Sie einen Index für Kunden-ID erstellen, hat das DBMS Möglichkeiten, den Index sehr schnell zu durchsuchen. Es ist keine sequentielle Suche, sondern je nach Datenbank eine binäre Suche oder eine andere effiziente Methode. Genau wie spielt keine Rolle, akzeptieren Sie, dass es viel schneller als sequentiell ist. Der Index führt ihn dann direkt zu dem entsprechenden Datensatz oder den entsprechenden Datensätzen. Wenn Sie außerdem angeben, dass der Index "eindeutig" ist, weiß die Datenbank, dass es nur einen geben kann, sodass sie keine Zeit damit verschwendet, nach einem zweiten zu suchen. (Und das DBMS wird Sie daran hindern, eine Sekunde hinzuzufügen.)
Betrachten Sie nun diese Abfrage:
select name
from customer
where city='Albany' and state='NY';
Jetzt haben wir zwei Bedingungen. Wenn Sie nur für eines dieser Felder einen Index haben, verwendet das DBMS diesen Index, um eine Teilmenge der Datensätze zu finden, und durchsucht diese dann sequentiell. Wenn Sie beispielsweise einen Bundesstaatsindex haben, findet das DBMS schnell den ersten Datensatz für NY, sucht dann sequentiell nach city='Albany' und hört auf zu suchen, wenn es den letzten Datensatz für NY erreicht.
Wenn Sie einen Index haben, der beide Felder enthält, d. h. „Index für Kunde erstellen (Bundesland, Stadt)“, dann kann das DBMS sofort auf die richtigen Datensätze zoomen.
Wenn Sie zwei separate Indizes haben, einen für jedes Feld, hat das DBMS verschiedene Regeln, die es anwendet, um zu entscheiden, welcher Index verwendet werden soll. Auch hier hängt die genaue Vorgehensweise von dem jeweiligen DBMS ab, das Sie verwenden, aber im Grunde versucht es, Statistiken über die Gesamtzahl der Datensätze, die Anzahl der verschiedenen Werte und die Verteilung der Werte zu führen. Dann durchsucht es diese Datensätze sequentiell nach denen, die die andere Bedingung erfüllen. In diesem Fall würde das DBMS wahrscheinlich feststellen, dass es viel mehr Städte als Bundesstaaten gibt, sodass es mithilfe des Städteindexes schnell zu den „Albany“-Datensätzen zoomen kann. Dann durchsucht es diese sequentiell und prüft den Status von jedem mit 'NY'. Wenn Sie Aufzeichnungen für Albany, Kalifornien haben, werden diese übersprungen.
Jeder Join erfordert eine Art Suche.
Angenommen, wir schreiben
select customer.name
from transaction
join customer on transaction.customerid=customer.customerid
where transaction.transactiondate='2010-07-04' and customer.type='Q';
Nun muss das DBMS entscheiden, welche Tabelle zuerst gelesen werden soll, die entsprechenden Datensätze von dort auswählen und dann die passenden Datensätze in der anderen Tabelle finden.
Wenn Sie einen Index für transaction.transactiondate und customer.customerid hätten, wäre der beste Plan wahrscheinlich, alle Transaktionen mit diesem Datum zu finden und dann für jede davon den Kunden mit der passenden Kunden-ID zu finden und dann zu überprüfen, ob der Kunde dies getan hat der richtige Typ.
Wenn Sie keinen Index für customer.customerid haben, könnte das DBMS die Transaktion schnell finden, aber dann müsste es für jede Transaktion die Kundentabelle nacheinander durchsuchen, um nach einer passenden Kunden-ID zu suchen. (Dies wäre wahrscheinlich sehr langsam.)
Nehmen Sie stattdessen an, dass die einzigen Indizes, die Sie haben, auf transaction.customerid und customer.type sind. Dann würde das DBMS wahrscheinlich einen völlig anderen Plan verwenden. Es würde wahrscheinlich die Kundentabelle nach allen Kunden mit dem richtigen Typ durchsuchen, dann für jeden von ihnen alle Transaktionen für diesen Kunden finden und sie der Reihe nach nach dem richtigen Datum durchsuchen.
Der wichtigste Schlüssel zur Optimierung besteht darin, herauszufinden, welche Indizes wirklich helfen, und diese Indizes zu erstellen. Zusätzliche, ungenutzte Indizes belasten die Datenbank, da es Arbeit kostet, sie zu pflegen, und wenn sie nie verwendet werden, ist dies verschwendete Mühe.
Mit dem EXPLAIN-Befehl können Sie feststellen, welche Indizes das DBMS für eine bestimmte Abfrage verwendet. Ich verwende dies ständig, um festzustellen, ob meine Abfragen gut optimiert sind oder ob ich zusätzliche Indizes erstellen sollte. (Lesen Sie die Dokumentation zu diesem Befehl für eine Erläuterung seiner Ausgabe.)
Vorbehalt:Denken Sie daran, dass ich gesagt habe, dass das DBMS Statistiken über die Anzahl der Datensätze und die Anzahl der unterschiedlichen Werte usw. in jeder Tabelle führt. EXPLAIN kann Ihnen heute einen völlig anderen Plan geben als gestern, wenn sich die Daten geändert haben. Wenn Sie beispielsweise eine Abfrage haben, die zwei Tabellen verbindet und eine dieser Tabellen sehr klein und die andere groß ist, wird sie dazu neigen, zuerst die kleine Tabelle zu lesen und dann übereinstimmende Datensätze in der großen Tabelle zu finden. Das Hinzufügen von Datensätzen zu einer Tabelle kann sich ändern, was größer ist, und somit dazu führen, dass das DBMS seinen Plan ändert. Daher sollten Sie versuchen, EXPLAINS gegen eine Datenbank mit realistischen Daten durchzuführen. Das Ausführen gegen eine Testdatenbank mit 5 Datensätzen in jeder Tabelle ist weitaus weniger wert als das Ausführen gegen eine Live-Datenbank.
Nun, es gäbe noch viel mehr zu sagen, aber ich möchte hier kein Buch schreiben.