Ho una struttura di tabella partizionata come:
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);
....
E così via. Ogni tabella ha circa 20 milioni di righe.
Se eseguo una query per un campione di sensori e un campione di timestamp nella WHERE
clausola, il piano di query mostra le tabelle corrette selezionate e gli indici utilizzati, ad esempio:
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' ;
Tuttavia, se utilizzo un CTE o inserisco i valori di data / ora in una tabella (non mostrato, anche con gli indici nella tabella temporanea).
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)
)
Qualcosa di simile al sotto
SET constraint_exclusion = on;
SELECT * FROM measurements
INNER JOIN sensor_sample USING (sensor_id)
WHERE tx BETWEEN start_ts AND end_ts
Esegue una scansione dell'indice su ogni tabella. Che è ancora relativamente veloce, ma con una crescente complessità delle query, questo può trasformarsi in scansioni seq che finiranno per essere molto lente per il recupero di ~ 40K righe da un sottoinsieme limitato di tabelle partizionate (4-5 di 50).
Sono interessato che qualcosa di simile a questo è il problema.
Per espressioni non banali devi ripetere la condizione più o meno alla lettera nelle query per far capire al pianificatore di query Postgres che può fare affidamento sul vincolo CHECK. Anche se sembra ridondante!
Come posso migliorare il partizionamento e la struttura delle query per ridurre la probabilità di eseguire scansioni seq su tutti i miei dati?