PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Données redondantes dans les instructions de mise à jour

En raison de PostgreSQL MVCC, une UPDATE est effectivement un peu comme un DELETE plus un INSERT . À l'exception notable des valeurs grillées - voir :

  • Postgres réécrit-il toute la ligne lors de la mise à jour ?

(Et des différences mineures pour les tuples de tas uniquement - DELETE + INSERT démarre une nouvelle chaîne HOT - mais cela n'a aucune incidence sur l'affaire en cours.)

Pour être précis, la ligne "supprimée" est simplement invisible pour toute transaction commençant après la validation de la suppression, et aspirée plus tard. Par conséquent, du côté de la base de données, y compris la manipulation d'index, il n'y a en fait aucune différence entre les deux déclarations. (Des exceptions s'appliquent, continuez à lire.) Cela augmente un peu le trafic réseau (en fonction de vos données) et nécessite un peu d'analyse.

J'ai étudié un peu plus les mises à jour HOT après l'entrée de @araqnid et j'ai effectué quelques tests. Les mises à jour sur les colonnes qui ne changent pas réellement la valeur ne font aucune différence que ce soit en ce qui concerne les mises à jour HOT. Ma réponse tient. Voir les détails ci-dessous.

Cela s'applique également aux attributs grillés, car ceux-ci ne sont pas non plus touchés à moins que les valeurs ne changent réellement .

Cependant , si vous utilisez des déclencheurs par colonne (introduit avec la page 9.0), cela peut avoir des effets secondaires indésirables !

Je cite le manuel sur les déclencheurs :

... une commande telle que UPDATE ... SET x = x ... déclenchera un déclencheur sur la colonne x , même si la valeur de la colonne n'a pas changé .

J'insiste sur moi.

Les couches d'abstraction sont pratiques. Ils sont utiles pour les développeurs analphabètes SQL ou si l'application doit être portable entre différents RDBMS. En revanche, ils peuvent réduire les performances et introduire des points de défaillance supplémentaires. Je les évite autant que possible.

Mises à jour HOT (tuple de tas uniquement)

Les Heap-Only Tuples ont été introduits avec Postgres 8.3, avec des améliorations importantes dans 8.3.4 et 8.4.9.
Les notes de version pour Postgres 8.3 :

UPDATE s et DELETE s laissent les tuples morts derrière, tout comme INSERT échoué s.Auparavant uniquement VACUUM pourrait récupérer l'espace occupé par les tuples morts. L'espace de tuple mort WithHOT peut être automatiquement récupéré au moment de INSERT ou UPDATE si aucune modification n'est apportée aux colonnes indexées . Cela permet des performances plus constantes. De plus, HOT évite d'ajouter des entrées d'index en double.

C'est moi qui souligne. Et "aucune modification" inclut les cas où les colonnes sont mises à jour avec la même valeur qu'elles contiennent déjà. J'ai en fait testé , car je n'étais pas sûr.

En fin de compte, le fichier README.HOT complet dans le code source le confirme.

Les colonnes grillées ne font pas non plus obstacle aux mises à jour HOT. Le tuple mis à jour à chaud est simplement lié au(x) même(s) tuple(s) inchangé(s) dans le toast fork de la relation. Les mises à jour HOT fonctionnent même avec des valeurs grillées dans la liste cible (réellement modifiées ou non). Si les valeurs toastées sont modifiées, cela implique évidemment des écritures dans la fourchette de relation toast. J'ai également testé tout cela.

Ne me croyez pas sur parole, voyez par vous-même. Postgres fournit quelques fonctions pour vérifier les statistiques. Exécutez votre UPDATE avec et sans toutes les colonnes et vérifiez si cela fait une différence.

-- Number of rows HOT-updated in table:
SELECT pg_stat_get_tuples_hot_updated('table_name'::regclass::oid)

-- Number of rows HOT-updated in table, in the current transaction:
SELECT pg_stat_get_xact_tuples_hot_updated('table_name'::regclass::oid)

Ou utilisez pgAdmin. Sélectionnez votre tableau et inspectez l'onglet "Statistiques" dans la fenêtre principale.

Sachez que les mises à jour HOT ne sont possibles que lorsqu'il y a de la place pour la nouvelle version de tuple sur la même page du fork de relation principal. Un moyen simple de forcer cette condition est de tester avec une petite table qui ne contient que quelques lignes. La taille de la page est généralement de 8 Ko, il doit donc y avoir de l'espace libre sur la page.