J'ai une structure de table partitionnée comme:
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);
....
Etc. Chaque table comprend environ 20 millions de lignes.
Si je demande un échantillon de capteurs et un échantillon d'horodatages dans la WHERE
clause, le plan de requête montre les bonnes tables sélectionnées et les index utilisés, par exemple:
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' ;
Cependant, si j'utilise un CTE ou que je mets les valeurs d'horodatage dans une table (non affichées, même avec des index sur la table temporaire).
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)
)
Quelque chose comme ci-dessous
SET constraint_exclusion = on;
SELECT * FROM measurements
INNER JOIN sensor_sample USING (sensor_id)
WHERE tx BETWEEN start_ts AND end_ts
Effectue une analyse d'index sur chaque table. Ce qui est encore relativement rapide, mais avec la complexité croissante des requêtes, cela peut se transformer en analyses séquentielles qui finiront par être très lentes pour récupérer ~ 40K lignes à partir d'un sous-ensemble limité de tables partitionnées (4-5 sur 50).
Je crains que quelque chose comme ça soit le problème.
Pour les expressions non triviales, vous devez répéter la condition plus ou moins verbatim dans les requêtes pour que le planificateur de requêtes Postgres comprenne qu'il peut s'appuyer sur la contrainte CHECK. Même si cela semble redondant!
Comment puis-je améliorer le partitionnement et la structure des requêtes pour réduire la probabilité d'exécuter des analyses seq sur toutes mes données?