Ich habe eine partitionierte Tabellenstruktur wie:
CREATE TABLE measurements (
sensor_id bigint,
tx timestamp,
measurement int
);
CREATE TABLE measurements_201201(
CHECK (tx >= '2012-01-01 00:00:00'::timestamp without time zone
AND tx < ('2012-01-01 00:00:00'::timestamp without time zone + '1 mon'::interval))
)INHERITS (measurements);
CREATE INDEX ON measurements_201201(sensor_id);
CREATE INDEX ON measurements_201201(tx);
CREATE INDEX ON measurements_201201(sensor_id, tx);
....
Und so weiter. Jede Tabelle hat ungefähr 20 Millionen Zeilen.
Wenn ich in der WHERE
Klausel nach einem Beispiel für Sensoren und einem Beispiel für Zeitstempel frage, zeigt der Abfrageplan die richtigen ausgewählten Tabellen und verwendeten Indizes an, z. B.:
SELECT *
FROM measurements
INNER JOIN sensors TABLESAMPLE BERNOULLI (0.01) USING (sensor_id)
WHERE tx BETWEEN '2015-01-04 05:00' AND '2015-01-04 06:00'
OR tx BETWEEN '2015-02-04 05:00' AND '2015-02-04 06:00'
OR tx BETWEEN '2014-03-05 05:00' AND '2014-04-07 06:00' ;
Wenn ich jedoch einen CTE verwende oder die Zeitstempelwerte in eine Tabelle einfüge (nicht angezeigt, auch nicht mit Indizes für die temporäre Tabelle).
WITH sensor_sample AS(
SELECT sensor_id, start_ts, end_ts
FROM sensors TABLESAMPLE BERNOULLI (0.01)
CROSS JOIN (VALUES (TIMESTAMP '2015-01-04 05:00', TIMESTAMP '2015-01-04 06:00'),
(TIMESTAMP '2015-02-04 05:00', TIMESTAMP '2015-02-04 06:00'),
(TIMESTAMP '2014-03-05 05:00', '2014-04-07 06:00') ) tstamps(start_ts, end_ts)
)
So etwas wie das Folgende
SET constraint_exclusion = on;
SELECT * FROM measurements
INNER JOIN sensor_sample USING (sensor_id)
WHERE tx BETWEEN start_ts AND end_ts
Führt für jede Tabelle einen Index-Scan durch. Dies ist immer noch relativ schnell, kann jedoch mit zunehmender Komplexität der Abfragen zu seq-Scans führen, die zum Abrufen von ~ 40 KB-Zeilen aus einer begrenzten Teilmenge partitionierter Tabellen (4-5 von 50) sehr langsam sind.
Ich bin besorgt darüber , dass so etwas wie dies das Problem ist.
Für nicht triviale Ausdrücke müssen Sie die mehr oder weniger wörtliche Bedingung in Abfragen wiederholen, damit der Postgres-Abfrageplaner versteht, dass er sich auf die CHECK-Einschränkung stützen kann. Auch wenn es überflüssig erscheint!
Wie kann ich die Partitionierung und die Abfragestruktur verbessern, um die Wahrscheinlichkeit zu verringern, dass für alle meine Daten Seq-Scans ausgeführt werden?