Suppression en bloc pour une grande table dans MySQL

9

J'ai une table de notification contenant environ 100 millions de lignes d'hôte dans Amazon RDS avec 1000 IOPS, et je souhaite supprimer ces lignes de plus d'un mois.

Si je le fais DELETE FROM NOTIFICATION WHERE CreatedAt < DATE_SUB(CURDATE(), INTERVAL 30 day);, tous les IOPS seront pris, le processus prendra des heures et de nombreuses nouvelles entrées ne pourront pas être insérées en raison de "Délai d'attente de verrouillage dépassé; essayez de redémarrer la transaction".

J'essayais de faire la manière décrite ici: http://mysql.rjweb.org/doc.php/deletebig Cependant, j'utilise UUID au lieu d'incrémenter l'ID.

Quelle est la manière correcte et efficace de supprimer ces lignes sans affecter les nouvelles données insérées / mises à jour?

Tianyi Cong
la source
Vous avez raison ypercube, je l'ai rectifié. Merci d'avoir souligné!
Tianyi Cong
La suppression d'enregistrements en plus petits morceaux, n'impacte pas l'opération d'insertion, je l'ai essayé avec boucle, et il termine la suppression de 70 millions d'enregistrements en moins d'une heure rathishkumar.in/2017/12/…
Rathish

Réponses:

11

Créez une table temporaire, activez-la, puis copiez-y les données des 30 derniers jours.

#
# Make empty temp table
#
CREATE TABLE NOTIFICATION_NEW LIKE NOTIFICATION;
#
# Switch in new empty temp table
#
RENAME TABLE NOTIFICATION TO NOTIFICATION_OLD,NOTIFICATION_NEW TO NOTIFICATION;
#
# Retrieve last 30 days data 
#
INSERT INTO NOTIFICATION SELECT * FROM NOTIFICATION_OLD
WHERE CreatedAt >= DATE_SUB(CURDATE(), INTERVAL 30 DAY);

Pendant vos heures de repos, laissez tomber l'ancienne table

DROP TABLE NOTIFICATION_OLD;

Voici les avantages de faire DELETE comme ça

  1. NOTIFICATION est vidé rapidement en basculant dans une table vide.
  2. NOTIFICATION est immédiatement disponible pour les nouveaux INSERT
  3. Les 30 jours restants sont ajoutés dans NOTIFICATIONtandis que de nouveaux INSERT peuvent avoir lieu.
  4. La suppression de l'ancienne version de NOTIFICATIONn'interfère pas avec les nouveaux INSERT
  5. REMARQUE: J'ai recommandé de faire des appâts et des commutateurs pour les suppressions de table avant: (Voir mon article du 19 juillet 2012: Optimisation de la requête DELETE sur la table MEMORY de MySQL )

Essaie !!!

RolandoMySQLDBA
la source
Merci la réponse Rolando! Comment MySql gère-t-il en interne la table de dépôt? Supprimez d'abord toutes les colonnes, puis supprimez le tableau ou autre chose? Cela prendra-t-il beaucoup plus de temps que de supprimer ces cloumns?
Tianyi Cong
J'applique cette stratégie sur la mise en scène, la commande rename doit-elle commencer par "RENAME TABLE"?
Tianyi Cong
y aurait-il une différence si je l'utilisais dans un bloc de transaction, en gardant à l'esprit le délai d'attente de verrouillage, aurait-il également des inconvénients si ma table réelle est vraiment énorme qui est maintenant renommée et doit être supprimée
Muhammad Omer Aslam
1
@MuhammadOmerAslam dans ce cas, le fichier ibdata1 (espace de table système) ne ferait que croître dans les journaux d'annulation. C'est particulièrement le cas quand ibdata1 commençait à grossir en taille de fichier (Voir mon ancien article dba.stackexchange.com/questions/40730/… ). Vous devez faire preuve de plus de prudence en utilisant pt-archiver comme mentionné dans la réponse d'Akuzminsky ALTER TABLE ENGINE=InnoDB .
RolandoMySQLDBA
1
@MuhammadOmerAslam L'approche ci-dessus serait parfaite lorsque vous avez programmé des temps d'arrêt. Suivre le lien dans la réponse d' Akuzminsky ( percona.com/doc/percona-toolkit/LATEST/pt-archiver.html ). Vous pouvez utiliser pt-archiver pour archiver des données ou simplement supprimer des données sans archiver.
RolandoMySQLDBA
3

Mon préféré est pt-archiver de Percona Toolkit. Il prend en charge la charge MySQL, le retard de réplication.

akuzminsky
la source
Merci la réponse akuzminsky! Je vais y jeter un œil. J'avais l'habitude d'essayer Percona lorsque je voulais modifier cette table de notification avec pt-online-schema-change. Cependant, il avait besoin du privilège SUPER pour effectuer la modification, qui n'est pas fournie par RDS. BTW connaissez-vous un bon moyen de modifier une énorme table?
Tianyi Cong
@TianyiCong vous avez une nouvelle question: veuillez la poser comme une nouvelle question et peut-être commenter ici avec un lien, ne la posez pas dans les commentaires ce n'est pas ainsi que fonctionne ce site.
Jack dit d'essayer topanswers.xyz
-2

créer la table notification_temp comme sélectionnez * à partir de la notification où CreatedAt <DATE_SUB (CURDATE (), INTERVAL 30 jours);

notification de table de dépôt;

RENOMMER notification_temp TO NOTIFICATION;

user52557
la source
Et cela n'affectera pas les nouvelles données insérées / mises à jour? Je ne pense pas.
Colin 't Hart
Cette méthode a 2 problèmes 1) rend NOTIFICATION indisponible pendant la durée de DROP TABLE. 2) Les INSERTS qui se produisent pendant le CREATE TABLEsont manqués.
RolandoMySQLDBA
Un autre problème: il faut direRENAME TABLE notification_temp ...
RolandoMySQLDBA