4 votes

Pourquoi l'opération ON DELETE CASCADE prend-elle parfois beaucoup de temps sur Postgres 9 ?

J'ai quelques relations entre des tables qui sont toutes liées à une table "propriétaire". Donc, pour les besoins de l'exemple :

  • Propriétaire de la table avec PK id
  • Table Parent avec PK id et FK owner_id se référant à Owner.id, avec un index sur celle-ci, et ON DELETE CASCADE .
  • Table Child avec PK id et FK parent_id faisant référence à Parent.id, avec un index sur celle-ci, et ON DELETE CASCADE .

La table Child est énorme (~50 millions de lignes), la table Parent a quelques milliers de lignes, et la table Owner est très petite (~10 lignes).

Il existe quelques autres tables liées au propriétaire et au parent, mais elles sont relativement petites (quelques milliers) et ont également des index sur des clés étrangères, et ON CASCADE DELETE .

Parfois, lorsque je supprime une ligne de propriétaire, la suppression en cascade de toutes les lignes (environ 12 millions de lignes d'enfant et un millier de lignes de parent) fonctionne très rapidement (quelques secondes), mais parfois cela prend presque une heure.

Comment puis-je trouver la cause de ce problème ? J'ai fait explain sur delete from child where parent_id in (select id from parent where owner_id = 1) où 1 est l'identifiant d'une des lignes du propriétaire (j'ai essayé plusieurs identifiants pour être sûr) et il dit qu'il utilise Bitmap Heap Scan -> Bitmap Index Scan et Index Scan. Cependant, je ne suis pas sûr que j'imite ce qui est réellement fait lorsqu'il y a un numéro d'identification de propriétaire. ON DELETE CASCADE déclencher. Comment puis-je comprendre ce qui cause ces énormes retards ? Se pourrait-il que Postgres préfère parfois effectuer un balayage séquentiel (en raison du nombre de lignes) ?

L'insertion des mêmes lignes ne prend que 8 minutes (y compris la logique de l'application et quelques milliers de validations de transactions). Je n'arrive donc pas à comprendre pourquoi la suppression directe prend autant de temps.

J'utilise Postgres 9.1.6.

0voto

Chris Travers Points 7808

Vous dites que parfois ça passe de quelques secondes à quelques heures. Il y a un nombre assez important de lignes à supprimer. Vous pouvez être confronté à toutes sortes de facteurs allant de la mise en cache des données aux verrous de lignes. Malheureusement, s'il s'agit de conditions transitoires, il peut être difficile de les retrouver lorsque le problème ne se produit pas.

Vous devriez commencer par examiner si vous pouvez trouver des modèles. Regardez SELECT * FROM pg_locks quand ça arrive. Vous devez également SELECT * FROM pg_stat_activity lorsque le problème survient pour voir où les verrous peuvent être retenus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X