2009-09-09 11 views
6

ATM Ich versuche zu lernen, wie Datenbank-Inidices effizient zu verwenden und würde gerne einige Experten-Eingabe erhalten. Ich habe derzeit keine Leistungsprobleme. Ich möchte nur wissen, wie Sie Ihre Indizes mit dieser Abfrage behandeln würde:Wie beschleunigt man diese Abfrage?

SELECT B.event, 
     COALESCE(B.system, C.surname || ' ' || C.forename) AS name, 
     C.label, 
     B.timestamp 
FROM A    
    INNER JOIN B ON A.event=B.event 
    INNER JOIN C ON B.state=C.id 
    LEFT OUTER JOIN D ON B.hur=D.id    
WHERE A.id IN(12,13,14,15,...) 
    ORDER BY B.event, B.timestamp 

A.id, C.id und D.id sind bereits Primärschlüssel

UPDATE normalerweise würde ich setzen INDEX (A.event) und INDEX (B.event, B.timestamp). Ist das richtig? Und was ist mit B.event, B.state und B.hur?

+0

Korrekt, aber prüfen Sie, ob B.timestamp tatsächlich verwendet wird. – Pomyk

+0

Wie groß sind die einzelnen Tabellen und wie viele Zeilen würden Sie bei einer bestimmten Abfrage erwarten? Welche Datenbank verwendest du? –

+0

Wie häufig werden Daten in die Tabellen eingefügt und wie häufig möchten Sie die Abfrage ausführen? –

Antwort

3

Ihre Abfrage wie diese Rewrite:

SELECT B.event, 
     COALESCE(B.system, C.surname || ' ' || C.forename) AS name, 
     C.label, 
     B.timestamp 
FROM B    
INNER JOIN 
     C 
ON  C.id = B.state 
LEFT OUTER JOIN 
     D 
ON  D.id = B.hur 
WHERE B.event IN 
     (
     SELECT event 
     FROM A 
     WHERE A.id IN (12, 13, 14, 15) 
     ) 
ORDER BY 
     B.event, B.timestamp 

, und erstellen Sie einen zusammengesetzten Index für B (event, timestamp)

2

Sie könnten Indizes in den WHERE- und ORDER BY-Klauseln hinzufügen. Dh A.event, B.event und B.timestamp.

+1

Fügen Sie keine Indizes blind hinzu. Siehe Lievens Antwort. Wenn Sie Indizes blind hinzufügen, kann dies die Performance beeinträchtigen, da jeder Index gepflegt werden muss. In einigen Fällen, wie bei kleinen Tabellen, wird dies weh tun, da das IO, das verwendet wurde, irgendwo anders verwendet werden könnte. Manchmal ist ein vollständiger Tabellenscan auf einer kleinen Tabelle besser als ein Index. – jim

+0

Ich bin versucht, meine Antwort zu löschen; jim's Kommentar ist jedoch eine nützliche Information, sollte die Antwort also belassen werden? – darasd

0
SELECT B.event, B.system, COALESCE(C.surname) || ' ' || COALESCE(C.forename) AS name, C.label, B.timestamp 
FROM A    
INNER JOIN B ON A.event=B.event 
INNER JOIN C ON B.state=C.id 
LEFT OUTER JOIN D ON B.hur=D.id    
WHERE A.event = ANY(:visits) 
ORDER BY B.event, B.timestamp 

Auch die ORDER BY wird die Dinge schlecht abbremsen. Stellen Sie sicher, diese indiziert werden:

A.event 
B.event 
B.state 
C.id 
B.timestamp 
3

ich diese Schritte in der Regel nehmen, wenn meine Fragen zu beschleunigen versucht

  1. analysieren den Ausführungsplan.
  2. versuchen Sie, Indizes zu erstellen, um Tabellenscans zu vermeiden.
  3. versuchen Sie, Indizes zu erstellen, um Index-Scans zu beseitigen.

Was Sie fragen, würden Sie nicht mit dem Erstellen von Indizes für

  • A.event
  • B.event
  • B.state
  • B.Hur
  • schief gehen
+0

Das Erstellen separater Indizes für B.event und B.state ist nicht das Gleiche wie das Erstellen eines Indexes für (B.event, B.state). Es ist wichtig, dies zu differenzieren, da es sich direkt auf die Leistung auswirkt. – MatBailie

+0

@Dems: Wenn das in meiner Antwort unklar blieb, bist du natürlich falsch. –

1

Ich würde Indizes zu allem hinzufügen, das verbunden ist, in der where-Klausel oder in der order by-Klausel.

In diesem Fall fügen Indizes der folgenden (unter der Annahme-ID-Felder sind Primärschlüssel und indexiert bereits):

  1. A.event
  2. B.event
  3. B.state
  4. B. Hur
  5. B.event, B.timestamp (kombinierten Index beider Felder)

Die fünfte, die eine Indexkombination ist, sollte die Reihenfolge um.

Sie müssen die Anzahl der Indizes abschwächen, um Leistungseinbußen beim Einfügen von Datensätzen in die Tabelle zu vermeiden (je mehr Indizes Sie der Tabelle hinzufügen, desto langsamer werden die Einfügungen und Aktualisierungen, da die Indizes aktualisiert werden müssen) .

2

Es ist wichtig zu beachten, dass die Reihenfolge der Felder im Index von Bedeutung ist.

Ein Index ist in gewissem Sinne ein Suchbaum. Wenn Sie indizieren (B.event, B.state), gruppiert der Baum alle Datensätze mit dem Feld "Ereignis" speichern und sortiert sie dann nach dem Feld "Status".

Wenn Sie dann diesen Index für "b.state = x" abfragen würden, wäre der Index von geringem Nutzen; Der Index wird zuerst nach dem "Ereignis" geordnet.


In Ihrem Beispiel:
- Filter A von seinem "Event" Feld
- beitreten A.event B.event
- beitreten B.state zu C.id
- Join B.hur = D.id
- Sortieren nach B.event, B.timestamp

Es ist wichtig zu beachten, dass die Optimierung auf die Statistik Ihrer Tabellen aussehen wird, und Indizes, kann dann neu ordnen, um die Reihenfolge der die Verknüpfungen. Das Ergebnis ist das gleiche, aber die Reihenfolge kann zu einer anderen Leistung führen, und der Job des Optimierers besteht darin, die beste Leistung zu finden.

In Ihrem Fall würde ich erwarten, dass die Reihenfolge von B.event extrem wichtig ist. Einfach weil das die Reihenfolge der resultierenden Ausgabe ist, UND es ist das Feld, nach dem Sie filtern.

Als nächstes schließen Sie B.state an C.id. Also, wenn C.id gut ist und indexiert, macht es den Join schneller. Aber auch die B-Tabellendaten in einer netten Reihenfolge können den Join schneller machen.

Aber ein Index für B.event und einen separaten Index für B.state kann wenig ergeben. Der B.State-Index wird nahezu sinnlos, da wir den B.event-Index verwenden. Wenn Sie die beiden zu einem Index kombinieren (b.event, dann b.state), kann der Ausführungsplan einen Weg finden, den b.state-Teil des Index zu verwenden.

Schließlich, wenn Sie alle Felder in den Index setzen, wird der Index größer, aber die Abfrage möglicherweise nie wirklich auf die Tabelle zu suchen. Die Information befindet sich im Index. Die Zeit, die benötigt wird, um von einem Index zur Tabelle zu gelangen, um die fehlenden Felder zu finden, ist ähnlich wie bei einem Join. Für die Leseleistung kann das Hinzufügen zusätzlicher Felder zu dem Index von wesentlicher Bedeutung sein.

Ich Wittenau auf jetzt, aber die Zusammenfassung ist dies:
- In der Regel separaten Index auf getrennten Feldern bekomme zusammen
nicht verwendet - Bei zusammengesetzten Indizes Sie die Reihenfolge der Felder festlegen, macht einen Unterschied
- Hinzufügen 'extra' Felder zum Index macht es größer, kann aber auch Anfragen schneller
- Die Reihenfolge des Ausführungsplans zählt mehr als die Reihenfolge Ihrer Abfrage
- Aber die Indizes, die Sie haben, kann die Reihenfolge bestimmen der Ausführungsplan

Diese Art von Arbeit hat keine kategorischen Antworten. Es ist so abhängig von Ihren Daten, dass es näher an einer Kunst ist.

Eine Option besteht darin, die Tabellen mit Indizes zu überladen, den resultierenden Ausführungsplan zu betrachten und die nicht benötigten Indizes zu löschen.

Aber selbst dort gilt ein Vorbehalt. Da der Ausführungsplan von Daten (und Tabellenstatistiken) abhängig ist, ist es sehr wichtig, reale Daten in den Tabellen zu haben. Während die Tabellen 10 oder 100 Zeilen haben, kann ein Ausführungsplan am schnellsten sein. Aber wenn Sie Millionen von Zeilen erhalten, kann sich der Ausführungsplan ändern und von verschiedenen Indizes profitieren.

2

Führen Sie erklären Analyse der Abfrage, und lesen Sie es - wenn es nicht hilft - setzen Sie die EXPLAIN-Analyse Ausgabe auf und überprüfen Sie, was es "sagt".