2017-04-21 5 views
0

erwartete ich habe eine TabelleSQL-Abfrage läuft langsamer als

foo(a1, a2, a3, a4, a5) 

a1 ist der Primärschlüssel. gibt es einen Nicht-Clustering-Index auf a5.

Ich habe eine einfache Abfrage:

SELECT * 
FROM foo 
WHERE a5/100 = 20; 

Diese Abfrage läuft deutlich langsamer. Das Aktualisieren der in der Abfrageplanung verwendeten Statistiken hat nicht viel geholfen.

Warum konnte das passieren? Was könnte ich falsch machen? Ich bin neu bei der Abfrageoptimierung.

+0

langsamer dann, was für WHERE a5/99 = <something> usw. obwohl

Docs helfen? Bitte geben Sie den Ausführungsplan an. –

+8

'WHERE a5/100 = 20;' -> versuchen Sie stattdessen 'WHERE a5 = 2000;' und stellen Sie sicher, dass ein Index für die Spalte 'a5' erstellt wurde. – krokodilko

+0

Bitte ** [EDIT] ** Ihre Frage und fügen Sie den Ausführungsplan hinzu, der mit ** 'explain (analyse, verbose)' ** erstellt wurde. [** Formatierter Text **] (http://stackoverflow.com/help/formatting) bitte, [keine Screenshots] (http://meta.stackoverflow.com/questions/285551/why-may-i-not -upload-images-of-code-auf-so-wenn-eine-Frage/285557 # 285557) –

Antwort

0

Sie verwenden einen Ausdruck für die Spalte im WHERE-Prädikat, sodass er nicht sargierbar ist (keinen Index verwenden).

Dies ist abgesehen von dem möglichen Problem der Kardinalität, das ist Datenverteilungen - wenn Ihre WHERE comditions mehr als etwa 40% der Zeile zurückgeben ein Index wird nutzlos.

EDIT

In einem Index, den Sie nach einem Wert suchen, wenn dieser Wert das Ergebnis eines Ausdrucks ist der Index used.Also Operator wie sein kippt: NICHT, NICHT IN, <> sind auch nicht-sargable weil Für eine Indexsuche benötigen Sie einen oder mehrere eindeutige Werte, damit der Optimierer einen festen Bereich definieren kann. Mit Ihren Berechnungen im laufenden Betrieb ändert sich der Wert ständig, so dass Sie die gesamte Tabelle scannen müssen.

+0

Danke für Ihre Antwort. Könntest du bitte etwas näher ausführen? Dies scheint ziemlich verdichtet zu sein. – foobar

+1

Es ist nicht ganz richtig, dass '<>' oder 'NOT IN' keinen Index verwenden können. Ein partieller Index, der mit 'where ... <> ...' definiert wird, könnte für eine solche Bedingung geeignet sein. –

+0

Ich habe eine zusätzliche Folgefrage: Was passiert, wenn ein Nicht-Clustering-Index für eine Spalte mit fehlendem/null erstellt wird? Werte? – foobar

0

Sie können einen Index für Ausdrücke anstelle der Basisdaten erstellen. Wenn Sie wissen, dass Sie immer a5 100 gehen zu teilen, können Sie einen Index mit tun:

CREATE INDEX ON foo ((a5/100)); 

Die zusätzlichen Klammern sind erforderlich.

Auf diese Weise kann jede Abfrage, die WHERE a5/100 = <something> hat, den Index nutzen.

Es wird nicht bei https://www.postgresql.org/docs/current/static/indexes-expressional.html

Verwandte Themen