web-dev-qa-db-fra.com

Trigger pour mettre à jour une vue matérialisée une fois après une transaction pertinente?

J'utilise PostgreSQL 9.6.

J'ai une vue matérialisée pour prendre en charge la recherche de texte intégral sur deux tables, que je vais appeler posts et tags. Les tables sont rarement mises à jour et recherchées fréquemment.

J'essaie de trouver une bonne stratégie pour courir REFRESH MATERIALIZED VIEW post_search.

La solution idéale serait une gâchette comme celle-ci: à la fin de (ou après) toute transaction qui modifie posts, tags et/ou posts_tags (Table de jointure), rafraîchissez la vue matérialisée exactement une fois.

Comment pourrais-je accomplir cela?

1
Nathan Long

Une solution ok utilisant des déclencheurs

C'est ce que je fais maintenant. Ce n'est pas exactement ce que je voulais parce que la gâchette incendie une fois par déclaration au lieu d'une fois par transaction. Mais ça marche pour l'instant.

(À l'avenir, nous envisagons d'utiliser une Table réelle pour la recherche au lieu d'une vue matérialisée et mettez à jour des lignes pertinentes individuelles via des déclencheurs au lieu de rafraîchir tout le MATTVIEW.)

Créez une fonction pour actualiser simultanément la vue matérialisée:

  CREATE OR REPLACE FUNCTION refresh_post_search()
  RETURNS TRIGGER LANGUAGE plpgsql
  AS $$
  BEGIN
  REFRESH MATERIALIZED VIEW CONCURRENTLY post_search;
  RETURN NULL;
  END $$;

Et créer une gâchette pour chacune des tables sous-jacentes:

  CREATE TRIGGER refresh_post_search
  AFTER INSERT OR UPDATE OR DELETE OR TRUNCATE
  ON posts
  FOR EACH STATEMENT
  EXECUTE PROCEDURE refresh_post_search();

  CREATE TRIGGER refresh_post_search
  AFTER INSERT OR UPDATE OR DELETE OR TRUNCATE
  ON posts_tags
  FOR EACH STATEMENT
  EXECUTE PROCEDURE refresh_post_search();

  CREATE TRIGGER refresh_post_search
  AFTER INSERT OR UPDATE OR DELETE OR TRUNCATE
  ON tags
  FOR EACH STATEMENT
  EXECUTE PROCEDURE refresh_post_search();
2
Nathan Long

Eh bien, probablement tu le fais mal. Alors que le verbe REFRESH peut connote autrement, vous réécrivez réellement la table lorsque vous l'exécutez. Ce type de charge de travail est lourd à courir dans une gâchette (bien que vous puissiez).

Cela n'a pas beaucoup de sens. Toi non plus

  1. Ne veux pas de MATERIALIZED VIEW;
  2. Voulez-vous une stratégie pour REFRESH pendant le temps d'arrêt ou le temps d'arrêt, ou périodiquement.

Le second est habituellement fait avec

  1. un simple cron, pg_crarr ou similaire
  2. à la fin de l'importation

Normalement, vous avez besoin de

  • Toujours-droite: utilisez une vue unie.
  • Périodiquement à droite: utilisez une vue matérialisée.
  • Fluide et droit: vous pouvez vérifier NOTIFY/EVENT ou bases de données série

C'est tout à fait possible qu'un MATERIALIZED VIEW Tout simplement pas ce que vous voulez.

1
Evan Carroll