Zawsze możesz wdrożyć własny stół służący jako „widok zmaterializowany”. To, co musiałeś zrobić wcześniej, MATERIALIZED VIEW
zostało zaimplementowane w Postgres 9.3.
Na przykład możesz utworzyć zwykły VIEW
:
CREATE VIEW graph_avg_view AS
SELECT xaxis, AVG(value) AS avg_val
FROM graph
GROUP BY xaxis;
I zmaterializuj wynik jako całość raz lub za każdym razem, gdy musisz zacząć od nowa:
CREATE TABLE graph_avg AS
SELECT * FROM graph_avg_view
(Lub użyj SELECT
instrukcji bezpośrednio, bez tworzenia a VIEW
.)
Następnie, w zależności od nieujawnionych szczegółów twojego przypadku użycia, możesz DELETE
/ UPDATE
/ INSERT
zmienić ręcznie.
Podstawowa instrukcja DML z modyfikującymi dane CTE dla tabeli, taka jak :
Zakładając, że nikt inny nie próbuje pisać do graph_avg
równoczesnego (odczyt ma problemu):
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;
Ale to najprawdopodobniej powinno być zoptymalizowane.
Podstawowy przepis:
- Dodaj
timestamp
domyślną kolumnę now()
do tabeli podstawowej. Nazwijmy to ts
.
- Jeśli masz aktualizacje, dodaj wyzwalacz, aby ustawić bieżący znacznik czasu dla każdej aktualizacji, która zmienia albo
xaxis
albo value
.
Utwórz mały stolik, aby zapamiętać znacznik czasu ostatniej migawki. Nazwijmy to mv
:
CREATE TABLE mv (
tbl text PRIMARY KEY
, ts timestamp NOT NULL DEFAULT '-infinity'
); -- possibly more details
Utwórz ten częściowy, wielokolumnowy indeks:
CREATE INDEX graph_mv_latest ON graph (xaxis, value)
WHERE ts >= '-infinity';
Użyj znacznika czasu ostatniej migawki jako predykatu w zapytaniach, aby odświeżyć migawkę przy doskonałym użyciu indeksu.
Pod koniec transakcji upuść indeks i utwórz go ponownie ze znacznikiem czasu transakcji, zastępując znacznik czasu w predykacie indeksu (początkowo '-infinity'
), który również zapisujesz w tabeli. Wszystko w jednej transakcji.
Zauważ, że indeks częściowy doskonale nadaje się do pokrycia INSERT
i UPDATE
operacji, ale nie DELETE
. Aby to pokryć, musisz wziąć pod uwagę cały stół. Wszystko zależy od dokładnych wymagań.