(PostreSQL 8.2, en cours d'exécution sur Windows XP)La meilleure façon de « matérialiser vue »
J'ai beaucoup de ces complexes requêtes qui prend plusieurs secondes pour exécuter chacun. Ils ne sont pas des "vues" en réalité, mais peuvent être traités comme tels.
J'ai décidé de conserver les enregistrements de résultat de ces "vues" dans des tables, que j'appelle des tables "auxiliaires".
Je peux garantir qu'il n'y a pas de changement de données après le calcul des tables "aux".
Prenons un exemple:
Supose J'ai une requête « X », donc je persiste c'est des résultats dans « Table_X ». Le jeu d'enregistrements est quelque chose comme ceci:
PERSON* FIELD_A* FIELD_ B FIELD_C
=======================================================
1 10 Value1 Value2
1 20 Value3 Value4
1 30 Value5 Value6
------------------------------------------------------
2 10 Value1 Value2
2 20 Value3 Value4
------------------------------------------------------
3 20 Value3 Value4
3 30 Value5 Value6
------------------------------------------------------
etc..
(*)Primary key is: person, field_a
Comme vous pouvez le voir, chaque « personne » a son sous-ensemble d'enregistrements dans ce tableau. Donc, je peux aller chercher rapidement ses enregistrements avec "select * from table_x where person = <person>"
.
Je chercherai toujours SEULEMENT par <person>
, et toutes mes requêtes ont le même "visage": "PERSON" + Some_Fields. IMPORTANT: Toutes les tables «aux» peuvent être lues (évidemment, avec de «vieilles» données jusqu'à ce que je m'engage) par d'autres transactions pendant que je les «renseigne». Mais je peux garantir qu'ils ne sont jamais mis à jour par ces transactions.
Mon processus actuel est:
- START TRANSACTION;
- DO A LOTS OF OPERATIONS ON DATABASE. INSERT/UPDATE/DELETE ON SEVERAL TABLES.
- AFTER THAT, I WILL CALCULATE "AUX" TABLES
- LOOP THROUGH ALL MY "QUERIES": (WHERE HERE WE CAN CALL AS "X")
- LOOP TROUGHT ALL "PERSON": (WHERE HERE WE CAN CALL AS <person>)
- DELETE FROM <TABLE_X> WHERE PERSON = <person>;
- INSERT INTO <TABLE_X> (PERSON, FIELD_A, FIELD_B, FIELD_C)
(SELECT <person>,
FIELDS...
FROM "LOTS OF TABLES"
JOIN "COMPLEX SQL"...
WHERE SOME_FIELD = <person>
);
- END LOOP "PERSON"
- END LOOP "QUERIES"
- COMMIT;
Considérations:
Certains de ces tableaux a des milliers de dossiers, et souvent seulement quelques dossiers ont besoin d'être mise à jour/supprimer/insérer si la comparaison avec le jeu d'enregistrements déjà "existant" dans la table. Comme la suppression et le "réinsertion" causent trop de "disque i/o" (si évident), et que j'ai besoin de "mettre à jour" juste quelques enregistrements, j'essaye d'obtenir une manière efficace de faire il. J'ai essayé de supprimer/mettre à jour/insérer dans des étapes séparées, le faire directement à partir de "requête complexe", mais cela prend trop de temps, car la requête a été exécutée 3 fois (une fois pour supprimer et une autre).
Des suggestions?
D'accord, faire la requête aussi vite que possible avant de vous engager dans cette voie. La vue matérialisée peut se compliquer rapidement si vous devez les tenir à jour avec les données actuelles. Voir http://www.pgcon.org/2008/schedule/events/69.en.html pour de bonnes informations. – AngerClown