Ви завжди можете реалізувати свою власну таблицю, яка подає як "матеріалізований вигляд". Це те, що ви повинні зробити раніше, MATERIALIZED VIEWбуло реалізовано в Postgres 9.3 в будь-якому випадку.
Наприклад, ви можете створити звичайну VIEW:
CREATE VIEW graph_avg_view AS
SELECT xaxis, AVG(value) AS avg_val
FROM graph
GROUP BY xaxis;
І одержати результат в цілому один раз або коли потрібно починати:
CREATE TABLE graph_avg AS
SELECT * FROM graph_avg_view
(Або використовувати SELECTоператор безпосередньо, не створюючи VIEW.)
Потім, залежно від нерозкритих деталей вашого випадку використання, ви могли DELETE/ UPDATE/ INSERTзмінити вручну.
Основний оператор DML з КТРОМ даних змін для вашої таблиці , як є :
Припускаючи , що ніхто інший НЕ намагається писати в graph_avgодночасно (читання це не проблема):
WITH del AS (
DELETE FROM graph_avg t
WHERE NOT EXISTS (SELECT 1 FROM graph_avg_view v WHERE v.xaxis = v.xaxis);
)
, upd AS (
UPDATE graph_avg t
FROM graph_avg_view v
WHERE t.xaxis = v.xaxis
AND t.avg_val <> v.avg_val
)
INSERT INTO graph_avg t
SELECT *
FROM graph_avg_view v
LEFT JOIN graph_avg t USING (xaxis)
WHERE t.xaxis IS NULL;
Але це, швидше за все, слід оптимізувати.
Основний рецепт:
- Додайте
timestampстовпчик із замовчуванням now()до базової таблиці. Давайте назвемо це ts.
- Якщо у вас є оновлення, додайте тригер, щоб встановити поточну позначку часу з кожним оновленням, яке змінюється
xaxisабо value.
Створіть крихітну таблицю, щоб запам'ятати часові позначки останнього знімка. Назвемо це mv:
CREATE TABLE mv (
tbl text PRIMARY KEY
, ts timestamp NOT NULL DEFAULT '-infinity'
); -- possibly more details
Створіть цей частковий, багатокольоновий індекс:
CREATE INDEX graph_mv_latest ON graph (xaxis, value)
WHERE ts >= '-infinity';
Використовуйте часову позначку останнього знімка як предикат у своїх запитах, щоб оновити знімок із ідеальним використанням індексу.
В кінці транзакції опустіть індекс і відтворіть його за допомогою часової позначки транзакції, замінивши позначку часу в предикаті індексу (спочатку '-infinity'), яку ви також збережете у своїй таблиці. Все за одну транзакцію.
Зауважте, що частковий індекс чудово підходить для покриття INSERTта UPDATEоперацій, але ні DELETE. Щоб покрити це, вам потрібно розглянути всю таблицю. Все залежить від точних вимог.