Documentation PostgreSQL 9.3.25 > Programmation serveur > Système de règles > Vues matérialisées | |
Vues et système de règles | Règles sur insert, update et delete |
Les vues matérialisées dans PostgreSQL™ utilisent le système des règles, tout comme les vues, mais les résultats persistent sous la forme d'une table. Les principales différences entre :
CREATE MATERIALIZED VIEW ma_vue_mat AS SELECT * FROM ma_table;
et :
CREATE TABLE ma_vue_mat AS SELECT * FROM ma_table;
sont que la vue matérialisée ne peut pas être directement mise à jour et que la requête utilisée pour créer la vue matérialisée est enregistrée exactement de la même façon qu'une requête d'une vue standard. Des données fraiches peuvent être générées pour la vue matérialisée avec cette commande :
REFRESH MATERIALIZED VIEW ma_vue_mat;
L'information sur une vue matérialisée est stockée dans les catalogues systèmes de PostgreSQL™ exactement de la même façon que pour les tables et les vues. Quand une vue matérialisée est référencée dans une requête, les données sont renvoyées directement à partir de la vue matérialisée, tout comme une table ; la règle est seulement utilisée pour peupler la vue matérialisée.
Bien que l'accès aux données d'une vue matérialisée est souvent bien plus rapide qu'accèder aux tables sous-jacentes directement ou par l'intermédiaire d'une vue, les données ne sont pas toujours fraiches. Cependant, quelques fois, des données plus fraiches ne sont pas nécessaires. Considérez une table qui enregistre les ventes :
CREATE TABLE facture ( no_facture integer PRIMARY KEY, no_vendeur integer, -- identifiant du vendeur date_facture date, -- date de la vente mtt_facture numeric(13,2) -- montant de la vente );
Si des personnes souhaitent grapher rapidement les données de vente, elles peuvent vouloir résumer l'information et ne pas avoir besoin des données incomplètes du jour :
CREATE MATERIALIZED VIEW resume_ventes AS SELECT no_vendeur, date_facture, sum(mtt_facture)::numeric(13,2) as mtt_ventes FROM facture WHERE date_facture < CURRENT_DATE GROUP BY no_vendeur, date_facture ORDER BY no_vendeur, date_facture; CREATE UNIQUE INDEX ventes_resume_vendeur ON resume_ventes (no_vendeur, date_facture);
Cette vue matérialisée peut être utile pour afficher un graphe dans l'affichage créée pour les vendeurs. Une tâche de fond pourrait être planifiée pour mettre à jour les statistiques chaque nuit en utilisant cette requête SQL :
REFRESH MATERIALIZED VIEW resume_ventes;
Une autre utilisation des vues matérialisées est de permettre un accès rapide aux données provenant d'un système distant, au travers d'un wrapper de données distantes. Un exemple utilisant file_fdw est donné ci-dessous, avec des chonométrages mais comme cela utilise le cache du système local, la différence de performances sur un wrapper de données distantes vers un système réellement distant pourrait être encore plus importante. Configuration ::
CREATE EXTENSION file_fdw; CREATE SERVER fichier_local FOREIGN DATA WRAPPER file_fdw; CREATE FOREIGN TABLE mots (mot text NOT NULL) SERVER fichier_local OPTIONS (filename '/etc/dictionaries-common/words'); CREATE MATERIALIZED VIEW vmots AS SELECT * FROM mots; CREATE UNIQUE INDEX idx_vmots ON vmots (mot); CREATE EXTENSION pg_trgm; CREATE INDEX vmots_trgm ON vmots USING gist (mot gist_trgm_ops); VACUUM ANALYZE vmots;
Maintenant, vérifions un mot. En utilisant file_fdw directement :
SELECT count(*) FROM mots WHERE mot = 'caterpiler'; count ------- 0 (1 row)
Le plan est le suivant :
Aggregate (cost=4125.19..4125.20 rows=1 width=0) (actual time=26.013..26.014 rows=1 loops=1) -> Foreign Scan on mots (cost=0.00..4124.70 rows=196 width=0) (actual time=26.011..26.011 rows=0 loops=1) Filter: (mot = 'caterpiler'::text) Rows Removed by Filter: 99171 Foreign File: /etc/dictionaries-common/words Foreign File Size: 938848 Total runtime: 26.081 ms
Si la vue matérialisée est utilisée à la place, la requête est bien plus rapide :
Aggregate (cost=4.44..4.45 rows=1 width=0) (actual time=0.074..0.074 rows=1 loops=1) -> Index Only Scan using idx_vmots on vmots (cost=0.42..4.44 rows=1 width=0) (actual time=0.071..0.071 rows=0 loops=1) Index Cond: (mot = 'caterpiler'::text) Heap Fetches: 0 Total runtime: 0.119 ms
Dans les deux cas, le mot est mal orthographié. Donc cherchons le bon mot. Toujours en utilisant file_fdw :
SELECT mot FROM mots ORDER BY mot <-> 'caterpiler' LIMIT 10; mot --------------- cater caterpillar Caterpillar caterpillars caterpillar's Caterpillar's caterer caterer's caters catered (10 rows)
Limit (cost=2195.70..2195.72 rows=10 width=32) (actual time=218.904..218.906 rows=10 loops=1) -> Sort (cost=2195.70..2237.61 rows=16765 width=32) (actual time=218.902..218.904 rows=10 loops=1) Sort Key: ((mot <-> 'caterpiler'::text)) Sort Method: top-N heapsort Memory: 25kB -> Foreign Scan on mots (cost=0.00..1833.41 rows=16765 width=32) (actual time=0.046..200.965 rows=99171 loops=1) Foreign File: /etc/dictionaries-common/words Foreign File Size: 938848 Total runtime: 218.966 ms
Et en utilisant la vue matérialisée :
Limit (cost=0.28..1.02 rows=10 width=9) (actual time=24.916..25.079 rows=10 loops=1) -> Index Scan using idx_vmots on vmots (cost=0.28..7383.70 rows=99171 width=9) (actual time=24.914..25.076 rows=10 loops=1) Order By: (mot <-> 'caterpiler'::text) Total runtime: 25.884 ms
Si vous pouvez tolérer des mises à jour périodiques sur les données distantes pour votre base locale, les bénéfices en performance seront importants.