web-dev-qa-db-fra.com

Supprimer des données d'une table d'un milliard de lignes en fonction de la clause WHERE

Je dois supprimer environ 400 millions de lignes d'une table de 1,3 milliard de lignes basée sur un champ de date indexé.

La table est d'environ 800 Go de taille.

Quel est le moyen le plus efficace de supprimer les données sans causer des effets indésirables? La table est très utilisée, ce qui signifie que de nombreux inserts et mises à jour (qui n'affectent pas les lignes à supprimer).

Il y a une fenêtre de maintenance qui serait la plus rapide, mais je ne pourrais peut-être pas obtenir une fenêtre de maintenance suffisante. Sur le côté retournement, je peux prendre mon temps avec la suppression, alors il n'y a pas de pressée.

4
sharadov

A figuré une meilleure façon de le faire

  1. Insert into new_tbl select * from old_tbl where start_date < now -INTERVAL '2 years'
  2. Pendant la fenêtre de temps d'arrêt:

    insert into new_tbl select * from old_tbl where id not in (select id from new_tbl ) and id not in ( select id from old_tbl)
    
  3. Renommer old_tbl à old_tbl_drop et new_tbl à old_tbl.

  4. Tomber old_tbl_drop.
0
sharadov

Réponse de la communauté Wiki :

Écrivez-vous un script de lot qui fait, disons, 10.000 Supprime et commet, sur 10 000 prochaines et ainsi de suite.

Vous devez choisir un numéro qui peut être supprimé et engagé rapidement, de sorte que vous n'interférez pas trop longtemps avec d'autres processus, mais soyez toujours utile de garder les choses en mouvement.

En supposant que vous puissiez trouver les enregistrements à supprimer, de manière opportune.

0
user126897

Si vous avez besoin de supprimer 400 m d'une table de 1,2 B. Cela signifie que vous devez marquer des lignes mortes de 400 m. C'est sensiblement plus rapide que d'écrire 3 fois plus que cela. De sorte que la manière la plus efficace sur PostgreSQL est un simple

DELETE FROM foo WHERE ...

BTW, supprimant un milliard que de nombreuses lignes n'est vraiment pas une grosse affaire. Essayez-le.

\timings

CREATE TABLE foo
AS
  SELECT x::bigint
  FROM generate_series(1,1200000000) AS gs(x);

DELETE FROM foo
WHERE x < 400000000;

Voir également

0
Evan Carroll