Puoi sempre implementare la tua tabella che funge da "vista materializzata". Questo è quello che dovevi fare prima di MATERIALIZED VIEW
essere implementato in Postgres 9.3 in entrambi i modi.
Ad esempio, puoi creare un semplice VIEW
:
CREATE VIEW graph_avg_view AS
SELECT xaxis, AVG(value) AS avg_val
FROM graph
GROUP BY xaxis;
E materializza il risultato nel suo insieme una volta o ogni volta che è necessario ricominciare da capo:
CREATE TABLE graph_avg AS
SELECT * FROM graph_avg_view
(O utilizzare SELECT
direttamente la dichiarazione, senza creare un VIEW
.)
Quindi, a seconda dei dettagli non divulgati del caso d'uso, è possibile DELETE
/ UPDATE
/ INSERT
modificare manualmente.
Un'istruzione DML di base con CTE che modificano i dati per la tabella come è :
Supponendo che nessun altro cerca di scrittura di graph_avg
concomitanza (lettura non è un problema):
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;
Ma questo dovrebbe probabilmente essere ottimizzato.
Ricetta base:
- Aggiungi una
timestamp
colonna per impostazione predefinita now()
alla tabella di base. Chiamiamolo ts
.
- Se si dispone di aggiornamenti, aggiungere un trigger per impostare il timestamp corrente con ogni aggiornamento che cambia
xaxis
o value
.
Crea una piccola tabella per ricordare il timestamp della tua ultima istantanea. Chiamiamolo mv
:
CREATE TABLE mv (
tbl text PRIMARY KEY
, ts timestamp NOT NULL DEFAULT '-infinity'
); -- possibly more details
Crea questo indice parziale a più colonne:
CREATE INDEX graph_mv_latest ON graph (xaxis, value)
WHERE ts >= '-infinity';
Utilizzare il timestamp dell'ultima istantanea come predicato nelle query per aggiornare l'istantanea con un utilizzo perfetto dell'indice.
Alla fine della transazione, rilasciare l'indice e ricrearlo con il timestamp della transazione sostituendo il timestamp nel predicato dell'indice (inizialmente '-infinity'
), che si salva anche nella tabella. Tutto in una transazione.
Si noti che l'indice parziale è ottimo per la copertura INSERT
e le UPDATE
operazioni, ma non DELETE
. Per coprirlo, devi considerare l'intero tavolo. Tutto dipende da requisiti esatti.