Я маю структуру таблиці з розділеними на зразок:
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);
....
І так далі. Кожна таблиця має приблизно 20М рядків.
Якщо я запитую зразок датчиків і зразок часових позначок у WHERE
пункті, план запитів показує, що обираються правильні таблиці та використовуються індекси, наприклад:
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' ;
Однак якщо я використовую CTE або поміщаю значення часових позначок у таблицю (не показано, навіть із індексами у тимчасовій таблиці).
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)
)
Щось подібне нижче
SET constraint_exclusion = on;
SELECT * FROM measurements
INNER JOIN sensor_sample USING (sensor_id)
WHERE tx BETWEEN start_ts AND end_ts
Виконує сканування індексу на кожній таблиці. Що все ще відносно швидко, але зі збільшенням складності запитів, це може перетворитись на послідовне сканування, яке в кінцевому підсумку буде дуже повільним для отримання ~ 40К рядків з обмеженого підмножини розділених таблиць (4-5 з 50).
Я стурбований тим , що - щось на зразок цього є проблемою.
Для нетривіальних виразів вам потрібно повторити більш-менш дослівно умову в запитах, щоб зрозуміти, що планувальник запитів Postgres розуміє, що він може покладатися на обмеження CHECK. Навіть якщо це здасться зайвим!
Як я можу покращити структуру розділів та запитів, щоб зменшити ймовірність запуску сканування послідовностей для всіх моїх даних?