Puoi sempre implementare la tua tabella che funge da "vista materializzata". Questo è quello che dovevi fare prima di MATERIALIZED VIEWessere 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 SELECTdirettamente la dichiarazione, senza creare un VIEW.)
Quindi, a seconda dei dettagli non divulgati del caso d'uso, è possibile DELETE/ UPDATE/ INSERTmodificare 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_avgconcomitanza (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
timestampcolonna 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
xaxiso 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 INSERTe le UPDATEoperazioni, ma non DELETE. Per coprirlo, devi considerare l'intero tavolo. Tutto dipende da requisiti esatti.