Siempre puede implementar su propia tabla que sirve como "vista materializada". Eso es lo que tenía que hacer antes de que MATERIALIZED VIEW
se implementara en Postgres 9.3 de cualquier manera.
Por ejemplo, puedes crear un plano VIEW
:
CREATE VIEW graph_avg_view AS
SELECT xaxis, AVG(value) AS avg_val
FROM graph
GROUP BY xaxis;
Y materialice el resultado como un todo una vez o cada vez que necesite comenzar de nuevo:
CREATE TABLE graph_avg AS
SELECT * FROM graph_avg_view
(O use la SELECT
declaración directamente, sin crear una VIEW
.)
Luego, dependiendo de los detalles no revelados de su caso de uso, podría DELETE
/ UPDATE
/ INSERT
cambiar manualmente.
Una declaración DML básica con CTE modificadores de datos para su tabla como es :
Suponiendo que nadie trate de otra persona a escribir al graph_avg
mismo tiempo (la lectura no es ningún 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;
Pero esto probablemente debería optimizarse.
Receta básica:
- Agregue una
timestamp
columna con valor predeterminado now()
a su tabla base. Digamos que es ts
.
- Si tiene actualizaciones, agregue un activador para establecer la marca de tiempo actual con cada actualización que cambie
xaxis
o value
.
Cree una tabla pequeña para recordar la marca de tiempo de su última instantánea. Llamémoslo mv
:
CREATE TABLE mv (
tbl text PRIMARY KEY
, ts timestamp NOT NULL DEFAULT '-infinity'
); -- possibly more details
Cree este índice parcial de varias columnas:
CREATE INDEX graph_mv_latest ON graph (xaxis, value)
WHERE ts >= '-infinity';
Use la marca de tiempo de la última instantánea como predicado en sus consultas para actualizar la instantánea con un uso de índice perfecto.
Al final de la transacción, suelte el índice y vuelva a crearlo con la marca de tiempo de la transacción reemplazando la marca de tiempo en el predicado de índice (inicialmente '-infinity'
), que también guarda en su tabla. Todo en una sola transacción.
Tenga en cuenta que el índice parcial es excelente para cubrir INSERT
y UPDATE
operaciones, pero no DELETE
. Para cubrir eso, debe considerar toda la tabla. Todo depende de los requisitos exactos.