tl; dr: le premier processus qui lit les données après leur validation définit des bits de conseil. Cela salira la page, créant une activité d'écriture. L'autre chose VACUUM
(mais pas les autres commandes) consiste à marquer la page comme visible, le cas échéant. VACUUM
devra finalement frapper la table pour geler les tuples.
Le travail qui doit être fait après un insert n'est pas vraiment un nettoyage, du moins pas dans le sens des autres travaux VACUUM
. Avant d'entrer dans les détails, notez que cette réponse est basée sur le code 9.6 actuel (non publié) et j'ignore les effets de la réplication en streaming, même si cela peut avoir un effet sur la visibilité.
En raison de MVCC , chaque fois que Postgres évalue si un tuple doit être visible pour une requête, il doit déterminer si la transaction qui a créé le tuple (enregistrée dans le champ caché xmin) a été validée, ainsi que d'autres critères. Ce contrôle est coûteux, donc dès que l'on sait qu'une transaction est visible pour toutes les transactions actuellement ouvertes, un "bit de conseil" est défini sur l'en-tête du tuple pour l'indiquer. Le réglage de ce bit salit la page, ce qui signifie qu'il devra être écrit sur le disque. Cela peut être très déroutant si la prochaine commande pour lire les données est SELECT
celle qui crée soudainement beaucoup de trafic d'écriture. L'exécution d'un VACUUM
après la validation de l'insertion évitera cela. Une autre distinction importante est queVACUUM
affichera TOUJOURS des tuples sur une page (tant qu'il aura le verrou de nettoyage sur la page), mais la plupart des autres commandes n'indiqueront que si la transaction d'insertion validée avant le démarrage de la commande.
Un point important sur l'écriture de tous ces bits de conseil est qu'il VACUUM
peut être limité (et l'autovacuum est limité par défaut). Les autres commandes ne sont pas limitées et généreront des données sales le plus rapidement possible.
VACUUM
est la seule méthode pour marquer les pages comme étant entièrement visibles, ce qui est une considération de performance importante pour certaines opérations (notamment les analyses d'index uniquement). Si vous faites un grand insert, il est très probable qu'il y ait beaucoup de pages avec rien mais des tuples nouvellement insérés. VACUUM
peut potentiellement marquer ces pages comme visibles, mais uniquement si la transaction en cours d'exécution la plus ancienne au VACUUM
démarrage était plus récente que la transaction qui a inséré les données .
En raison du fonctionnement de MVCC, les tuples qui ont été insérés il y a plus de ~ 2 milliards de transactions doivent être marqués comme " gelés ". Par défaut, autovacuum interviendra pour le faire toutes les 200 millions de transactions. L'exécution d'un vide manuel avec vacuum_freeze_min_age défini sur 0 après une insertion en vrac peut aider à réduire l'impact de cela. Plus agressivement, vous pouvez courir VACUUM FREEZE
sur la table après l'insertion. Cela "réinitialiserait l'horloge" lorsque le prochain arrêt sur gel se produirait.
Si vous souhaitez connaître les détails spécifiques, jetez un oeil à l' HEAPTUPLE_LIVE
affaire après l'appel à l' HeapTupleSatisfiesVacuum()
intérieur lazy_scan_heap()
. Voir aussi HeapTupleSatisfiesVacuum()
lui-même et le comparer à HeapTupleSatisfiesMVCC()
.
Il y a deux autres présentations qui pourraient être intéressantes. La première vidéo est disponible sur http://www.pgcon.org/2015/schedule/events/829.en.html , tandis que la seconde (qui je pense était un peu meilleure) sur https://www.youtube. com / watch? v = L8nErzxPJjQ
EXPLAIN (ANALYZE, BUFFERS) outputs. But, if I understand things correctly, some of the hint bits (at least
* COMMITTED` et*INVALID
) peuvent (pourraient) déjà être définies par leCOMMIT
ouROLLBACK
, non?