Vous pouvez toujours implémenter votre propre table servant de "vue matérialisée". C'est ce que vous deviez faire avant MATERIALIZED VIEW
était implémenté dans Postgres 9.3 de toute façon.
Par exemple, vous pouvez créer une plaine VIEW
:
CREATE VIEW graph_avg_view AS
SELECT xaxis, AVG(value) AS avg_val
FROM graph
GROUP BY xaxis;
Et matérialisez le résultat dans son ensemble une fois ou chaque fois que vous devez recommencer:
CREATE TABLE graph_avg AS
SELECT * FROM graph_avg_view
(Ou utilisez SELECT
directement l' instruction, sans créer de VIEW
.)
Ensuite, en fonction des détails non divulgués de votre cas d'utilisation, vous pouvez DELETE
/ UPDATE
/ INSERT
modifier les modifications manuellement.
Une instruction DML de base avec des CTE modifiant les données pour votre table en l'état :
En supposant que personne d' autre ne tente d' écrire à en graph_avg
même temps (lecture est pas un problème):
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;
Mais cela devrait probablement être optimisé.
Recette de base:
- Ajouter une
timestamp
colonne avec défaut now()
à votre table de base. Appelons ça ts
.
- Si vous avez des mises à jour, ajoutez un déclencheur pour définir l'horodatage actuel avec chaque mise à jour modifiant l'un
xaxis
ou l' autre value
.
Créez un petit tableau pour vous rappeler l'horodatage de votre dernier instantané. Appelons ça mv
:
CREATE TABLE mv (
tbl text PRIMARY KEY
, ts timestamp NOT NULL DEFAULT '-infinity'
); -- possibly more details
Créez cet index partiel multicolonne:
CREATE INDEX graph_mv_latest ON graph (xaxis, value)
WHERE ts >= '-infinity';
Utilisez l'horodatage du dernier instantané en tant que prédicat dans vos requêtes pour actualiser celui-ci avec une utilisation d'index parfaite.
À la fin de la transaction, supprimez l'index et recréez-le avec l'horodatage de la transaction en remplaçant l'horodatage dans le prédicat d'index (initialement '-infinity'
), que vous avez également enregistré dans votre table. Tout en une transaction.
Notez que l'index partiel est génial pour couvrir INSERT
et les UPDATE
opérations, mais pas DELETE
. Pour couvrir cela, vous devez considérer l'ensemble du tableau. Tout dépend des exigences exactes.