Ich habe eine PostgreSQL-Datenbank mit einer Mastertabelle und 2 untergeordneten Tabellen. Mein Mastertisch:
CREATE TABLE test (
id serial PRIMARY KEY,
date timestamp without time zone
);
CREATE INDEX ON test(date);
Meine Kindertische:
CREATE TABLE test_20150812 (
CHECK ( date >= DATE '2015-08-12' AND date < DATE '2015-08-13' )
) INHERITS (test);
CREATE TABLE test_20150811 (
CHECK ( date >= DATE '2015-08-11' AND date < DATE '2015-08-12' )
) INHERITS (test);
CREATE INDEX ON test_20150812(date);
CREATE INDEX ON test_20150811(date);
Wenn ich eine Abfrage wie folgt ausführe:
select * from test_20150812 where date > '2015-08-12' order by date desc;
Es kehrt sehr schnell zurück (20-30 Millisekunden). EXPLAIN
Ausgabe:
Limit (cost=0.00..2.69 rows=50 width=212)
-> Index Scan Backward using test_20150812_date_idx on test_20150812 (cost=0.00..149538.92 rows=2782286 width=212)
Index Cond: (date > '2015-08-12 00:00:00'::timestamp without time zone)
Wenn ich jedoch eine Abfrage wie folgt ausführe:
select * from test where date > '2015-08-12' order by date desc;
Es dauert lange (10-15 Sekunden). EXPLAIN
Ausgabe:
Limit (cost=196687.06..196687.19 rows=50 width=212)
-> Sort (cost=196687.06..203617.51 rows=2772180 width=212)
Sort Key: public.test.date
-> Result (cost=0.00..104597.24 rows=2772180 width=212)
-> Append (cost=0.00..104597.24 rows=2772180 width=212)
-> Seq Scan on test (cost=0.00..0.00 rows=1 width=1857)
Filter: (date > '2015-08-12 00:00:00'::timestamp without time zone)
-> Seq Scan on test_20150812 test (cost=0.00..104597.24 rows=2772179 width=212)
Filter: (date > '2015-08-12 00:00:00'::timestamp without time zone)
constraint_exclusion
ist ON
in meinem eingestellt postgresql.conf
. Daher sollte es nur am ausgeführt werden test_20150812
.
Ich sehe, dass, wenn eine Abfrage für die Mastertabelle ausgeführt wird, niemals Indizes verwendet werden. Wie kann ich es verbessern? Ich möchte alle meine Abfragen in meiner Haupttabelle stellen. Bei der Abfrage nach einem bestimmten Datum erwarte ich keinen Leistungsunterschied zwischen der Abfrage in der Mastertabelle oder der untergeordneten Tabelle.
test_20150812
vs.test_table_20150812
) zugunsten von Kurznamen aufzulösen . Sie haben vergessen, Ihre Version von Postgres anzugeben, und geben SieEXPLAIN (ANALYZE, BUFFERS)
nicht nur die Ausgabe von anEXPLAIN
. Auch seltsam:Seq Scan on test_table_20150812 test_table
(jetzt vereinfachttest_20150812 test
) ist nicht gültig erklären Ausgabe ...Antworten:
"Datum"
Nennen Sie Ihre
timestamp
Spalte nicht"Datum", das ist sehr irreführend. Besser noch, verwenden Sie den Basistypnamen "Datum" überhaupt nicht als Bezeichner. Dies ist fehleranfällig, führt zu verwirrenden Fehlermeldungen und ist ein reserviertes Wort in Standard-SQL . Sollte so etwas sein wie:Vorsichtsmaßnahmen
Beachten Sie diese Einschränkung mit Ausschluss von Einschränkungen :
Mutige Epmhasis Mine. Sie sind diesem ausgewichen , aber mit Ihrem verwirrenden Setup könnten Sie früh genug darüber stolpern.
Da Sie tägliche Partitionen haben:
Meine kühne Betonung. Wenn Sie mehr als ein paar Monate umfassen, versuchen Sie stattdessen wöchentliche oder monatliche Partitionen.
Nichtübereinstimmung in Prädikaten
Ihre Prüfbedingung:
Aber Ihre Anfrage hat die Bedingung:
Dies führt zu einer leichten Nichtübereinstimmung (wahrscheinlich falsch !) Und zwingt Postgres, den Zustand erneut zu überprüfen. Nicht gut, kann aber auch Ihre Frage nicht beantworten.
Verwenden Sie
>=
und machen Sie entweder die SpalteNOT NULL
oder hängen SieNULLS LAST
an die Anweisung:... und den Index übereinstimmen lassen.
Unreine
CHECK
EinschränkungDie
CHECK
Einschränkungen werden mitdate
Konstanten anstelle vontimestamp
Konstanten gespeichert . Sollte so etwas sein wie:Ausschluss von Einschränkungen
Du schreibst:
Wie Sie im Abfrageplan sehen können, werden nur
test
undtest_20150812
gescannt, aber nichttest_20150811
. Ergo: Der Ausschluss von Einschränkungen funktioniert trotz aller Abweichungen einwandfrei. Das ist nur ein weiterer falscher Weg.Gewann viele Schlachten, aber nicht den Krieg
Nachdem ich das alles bereinigt habe, sehe ich einen Bitmap-Index-Scan für die untergeordnete Tabelle anstelle Ihres seq-Scans. Immer noch langsamer als eine Abfrage nur für die untergeordnete Tabelle. Dies liegt offensichtlich daran, dass die übergeordnete Tabelle selbst auch übereinstimmende Zeilen enthalten kann, die mit dem Rest sortiert werden müssen, sodass das Ergebnis nicht einfach aus dem Index gelesen werden kann.
quelle
VACUUM ANALYZE
Ihre Tische.)