PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL:Warum verwendet diese Abfrage nicht meinen Index?

Wie Sie bereits bemerkt haben, hängt das Problem mit der Verwendung von anderen Operatoren als Gleichheit zusammen. Ein Index kann am effizientesten nur für die Spalten ganz links verwendet werden, die mit Gleichheit verglichen werden (plus eine Bereichsbedingung).

In Ihrem Beispiel:

create index i on t (a,b,c,d);
where a=1 and b=11 and c!=5 and d<8;

Es kann den Index nur für a verwenden und b effizient. Das bedeutet, dass die DB alle Zeilen holt, die mit a übereinstimmen und b Bedingung und prüft dann jede Zeile gegen die verbleibenden Bedingungen.

Wenn Sie den Filter auf c ändern auf gleich, werden (möglicherweise) weniger Zeilen abgerufen (nur diejenigen, die mit a übereinstimmen und b und c ) und vergleicht dann diese (weniger) Zeilen mit d Filter. Die Verwendung des Index ist in diesem Fall effizienter.

Im Allgemeinen bewertet der PostgreSQL-Abfrageplaner beide Optionen:(1) Verwenden des Index; (2) Durchführen eines SeqScan. Für beide errechnet es einen Kostenwert – je höher dieser ist, desto schlechter ist die zu erwartende Leistung. Folglich nimmt es denjenigen mit dem kleineren Kostenwert. So wird entschieden, ob der Index verwendet wird oder nicht, es gibt keine feste Schwelle.

Schließlich steht oben "plus eine Bereichsbedingung". Das bedeutet, dass es den Index nicht nur am effizientesten verwenden kann, wenn Sie Gleichheitszeichen verwenden, sondern auch für eine einzelne Bereichsbedingung.

In Anbetracht dessen, dass Ihre Abfrage nur eine einzige Bereichsbedingung enthält, würde ich vorschlagen, den Index wie folgt zu ändern:

create index i on t (a,b,d,c);

Jetzt kann es die Filter auf a verwenden und b und d effizient mit dem Index und muss nur die Zeilen wegfiltern, bei denen c!=5 . Obwohl dieser Index effizienter für Ihre Abfrage verwendet werden kann als Ihr ursprünglicher, bedeutet dies nicht automatisch, dass PG ihn verwendet. Das hängt von den Kostenvoranschlägen ab. Aber probiere es aus.

Schließlich, wenn das nicht schnell genug ist und den Wert 5 Sie verwenden im Ausdruck c!=5 konstant ist, könnten Sie einen partiellen Index in Betracht ziehen:

 create index i on t (a,b,d)
        where c!=5;

Sie können dies auch mit allen anderen Spalten tun, wenn die Werte, mit denen Sie sie vergleichen, Konstanten sind.

Referenzen: