Ви завжди можете реалізувати свою власну таблицю, яка подає як "матеріалізований вигляд". Це те, що ви повинні зробити раніше, 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
. Щоб покрити це, вам потрібно розглянути всю таблицю. Все залежить від точних вимог.