2 B-Tree-Indizes ODER 1 GiST-Index für tsrange - was wird besser abschneiden?

8

Ich habe eine Tabelle , die Daten Reservierung unter Verwendung der Spalten speichert starts_at& ends_atJedes Mal , wenn ich die Tabelle bin Abfrage überlappende Reservierungen zu finden, ich habe eine Möglichkeit , eine der folgenden Abfragen mit:

SELECT * FROM reservations
WHERE starts_at < '2014-01-03 00:00:00'
AND   ends_at   >='2014-01-01 00:00:00';

Oder

SELECT * FROM reservations
WHERE tsrange(starts_at, ends_at) && ('2014-01-01 00:00:00', '2014-01-03 00:00:00')

Ich habe reguläre B-Tree-Indizes für die Spalten starts_atund ends_at, daher werden sie bei der ersten Abfrage immer verwendet. Sofern ich keinen funktionalen GiST-Index für den tsrange definiere, führt die zweite Abfrage einen vollständigen Scan durch.

create index tsrange_idx on reservations using gist(tsrange(starts_at, ends_at)); 

Meine Frage ist, wenn die Tabelle wächst, welcher Index wird schneller sein? Wahrscheinlich ist die Antwort offensichtlich, wenn man sich den Ausführungsplan für Abfragen ansieht, aber ich bin mit dem Lesen von EXPLAIN ANALYZEAusgaben nicht vertraut .

Saurabh Nanda
quelle
dba.stackexchange.com/questions/39589/… Zusammenfassend sollte beides relativ gut funktionieren. Es ist schwierig, eine endgültige Antwort zu geben, ohne mit Daten aus der realen Welt zu testen.
Zack

Antworten:

13

Zeitstempel mit B-Tree-Index

Ich schlage eine dritte Option vor : Solange Ihre Tabelle zwei timestampSpalten enthält (die scheinbar definiert sind NOT NULL), würde ich einen einzelnen mehrspaltigen Index mit entgegengesetzter Sortierreihenfolge verwenden (sofern keine anderen Überlegungen zutreffen):

CREATE INDEX reservations_range_idx ON reservations using gist(starts_at, ends_at DESC);

Mehr in dieser verwandten Antwort:

Schauen Sie sich für die Abfrage den SQL-Standardoperator anOVERLAPS :

SELECT * FROM reservations
WHERE (starts_at, ends_at) OVERLAPS ('2014-01-01 00:00:00', '2014-01-03 00:00:00');

Mehr in dieser verwandten Frage zu SO:

Sollte schneller als zwei B-Tree-Indizes sein. Weniger Speicherplatz und billiger zu warten. Die Belastung für Schreibvorgänge ist gering

Bereichstyp mit GiST-Index

Bei großen Tabellen ist ein GiST-Index für einen Bereichstyp höchstwahrscheinlich schneller, da er besser skaliert. Der Speicher auf der Festplatte ist erheblich größer und die Indexwartung etwas teurer.

Wenn Sie diesen Weg gehen, ist es effizienter, Ihren Zeitstempel zunächst als Bereich ( tsrangeodertstzrange ) zu speichern . Ein einfacher GiST-Index ohne funktionalen Aspekt ist etwas schneller.

CREATE TABLE reservation (
  reservation_id serial PRIMARY KEY
 ,span tsrange
 , ...
);

CREATE INDEX reservation_span_gist_idx on reservations USING GiST (span);

Mit dem &&Operator "Überlappung" haben Sie bereits in der Frage angezeigt:

SELECT *
FROM   reservation 
WHERE  span && ('2014-01-01 00:00:00', '2014-01-03 00:00:00');

Möglicherweise sind Sie auch an einer Ausschlussbeschränkung interessiert , um Überschneidungen durch das Design auszuschließen, die einen GiST-Index wie den oben genannten automatisch implementiert. Das Handbuch enthält ein Codebeispiel . Diese verwandte Antwort auf SO enthält weitere Details:

Erwin Brandstetter
quelle