Warum verwendet PostgreSQL 9.5 nicht meinen neuesten Index für ORDER BY, obwohl ähnliche Indizes verwendet werden?

7

(Follow-up aus diesem Beitrag: Warum wird mein PostgreSQL-Ausdrucksindex nicht verwendet, wenn ich in einer Unterabfrage BESTELLEN? )

PostgreSQL 9.5.

Ich kann nicht alle Details preisgeben, habe aber table22 Spalten und 5 Indizes:

  1. Primärschlüssel ('pk'), text(btree)
  2. ein anderer text(btree)
  3. a timestamp with time zone(btree)
  4. a tsvector(Gin)
  5. mein neuester, a bigint(btree)

(Aus dem vorherigen Beitrag wissen Sie, dass ich versucht habe, das Erstellen dieser zusätzlichen Spalte zu vermeiden, und einfach einen Ausdrucksindex verwendet habe, bei dem zwei integerSpalten addiert wurden, ohne Erfolg. Die bigintSpalte hier hätte wahrscheinlich nur eine Ganzzahl sein können, aber ich habe eine erstellt Fehler beim Erstellen; es dauerte ungefähr eine Stunde, um die Spalte hinzuzufügen, zu füllen und neu zu indizieren. Ich hoffe, dass dies nicht relevant ist, erwähne es aber nur für den Fall, dass es so ist.)

Alle sind btree außer dem tsvector.

Die folgenden Abfragen dauern nur 12 ms und verwenden nur eine Index Scan:

  1. SELECT pk FROM table ORDER BY pk DESC LIMIT 10
  2. SELECT pk FROM table ORDER BY text_column DESC LIMIT 10
  3. SELECT pk FROM table ORDER BY timestamp_column DESC LIMIT 10

Aber wenn ich versuche, meinen neuen bigintIndex zu verwenden für ORDER BY:

SELECT pk FROM table ORDER BY bigint_column DESC LIMIT 10

... es dauert 2,7s und verwendet Limit -> Sort -> Seq Scan.

Meine "Betrugs" -Methode ist die Methode, mit der ich den Index am ehesten nutzen kann:

SELECT pk
FROM table
WHERE bigint_column > 1000000
ORDER BY bigint_column DESC LIMIT 10

Dies dauert 12 ms und verwendet Limit -> Sort -> Bitmap Heap Scan (bigint_column > 1000000) -> Bitmap Index Scan (bigint_column > 1000000).

Dies erfolgt nach dem VACUUM ANALYZEHinzufügen des Index.

Ich fand es seltsam, dass mein Ausdrucksindex in der anderen Frage nicht verwendet wurde. Jetzt ist es nur eine einfache alte Spalte (ich habe noch nicht einmal hinzugefügt, was die notwendigen Auslöser wären, um diesen Weg tatsächlich zu gehen.)

Warum wird mein neuester Index nicht verwendet, wenn die anderen drei "in Ordnung" funktionieren? (Wie in den Kommentaren unter https://dba.stackexchange.com/a/183290/28774 ausgeführt , wäre ein Nur-Index-Scan sogar noch besser. Ich verstehe nicht, warum all diese Abfragen nicht mindestens eine verwenden würden Index-Scan, geschweige denn ein Nur-Index-Scan anstelle eines vollständigen Seq-Scans.)

Die Indexdefinition hat DESC NULLS LAST(obwohl es sich um eine nicht nullbare Spalte handelt).

Kev
quelle

Antworten:

7

In PostgreSQL, ein Index, der DESC NULLS LASTnicht verwendet werden kann, um ein ORDER BYwas zu erfüllen DESC NULLS FIRST(was das Ordnen nach einfach einschließt, DESCweil dies impliziert NULLS FIRST). Dies ist auch dann der Fall, wenn die Spalte als definiert ist NOT NULL.

Sie können den Index entweder neu erstellen oder (da Sie wissen, dass die Spalte nicht null ist) NULLS LASTzu Ihren Abfragen hinzufügen ORDER BY, damit er mit dem vorhandenen Index übereinstimmt.

Beachten Sie, dass Sie PostgreSQLwissen, wie man einem Index rückwärts folgt, sodass ein Standardindex (der implizit ist ASC NULLS LAST) auch Ihre DESC NULLS FIRSTAbfrage erfüllen kann . Aus diesem Grund ist es selten wichtig, DESC in einem Index anzugeben. Es kann jedoch wichtig sein, anzugeben, nach welchem ​​Ende die NULL-Sortierung erfolgen soll.

jjanes
quelle
Ich habe auch dieses Problem mit einem GiST-Index. Es kann nur als ASC definiert werden (nicht sicher, ob NULL FIRST oder LAST ist). In beiden Fällen scheint der Index wie dieser Postgres nicht nach DESC bestellen zu wollen, ohne einen seq-Scan durchzuführen. Irgendein Rat?
Kevin Parker