web-dev-qa-db-fra.com

Le moyen le plus rapide de supprimer d'énormes tables MySQL

J'ai une énorme base de données MySQL (InnoDB) avec des millions de lignes dans la table des sessions qui ont été créées par un robot d'exploration sans lien et qui ne fonctionne pas, exécuté sur le même serveur que le nôtre. Malheureusement, je dois réparer le désordre maintenant.

Si j'essaie de truncate table sessions;, cela semble prendre un temps excessivement long (plus de 30 minutes). Je me fiche des données; Je veux juste que la table soit effacée le plus rapidement possible. Existe-t-il un moyen plus rapide ou devrai-je rester en place du jour au lendemain?

49
Kyle Kaitan

Le moyen le plus rapide consiste à utiliser DROP TABLE pour supprimer complètement la table et la recréer en utilisant la même définition. Si vous n'avez aucune contrainte de clé étrangère sur la table, vous devriez le faire.

Si vous utilisez une version de MySQL supérieure à 5.0.3, cela se produira automatiquement avec un TRUNCATE. Vous pouvez également obtenir des informations utiles dans le manuel. Il décrit le fonctionnement d’un TRUNCATE avec les contraintes FK. http://dev.mysql.com/doc/refman/5.0/en/truncate-table.html

EDIT: TRUNCATE n'est pas la même chose qu'un drop ou un DELETE FROM. Pour ceux qui ne comprennent pas les différences, veuillez consulter le lien du manuel ci-dessus. TRUNCATE agira comme un drop s'il le peut (s'il n'y a pas de FK), sinon il agit comme une clause DELETE FROM sans clause where.

46
womp

(Comme cela a été élevé dans les résultats de Google, j'ai pensé qu'un peu plus d'instructions pourrait être utile.)

MySQL offre un moyen pratique de créer des tables vides, comme les tables existantes, et une commande de renommage de table atomique. Ensemble, c’est un moyen rapide d’effacer les données:

CREATE TABLE new_foo LIKE foo;

RENAME TABLE foo TO old_foo, new_foo TO foo;

DROP TABLE old_foo;

Terminé

123
searlea

La meilleure façon de faire cela avec MySQL est la suivante:

DELETE from table_name LIMIT 1000;

Ou 10 000 (selon la rapidité avec laquelle cela se produit).

Mettez cela en boucle jusqu'à ce que toutes les lignes soient supprimées. 

S'il vous plaît, essayez ceci car cela fonctionnera réellement. Cela prendra du temps, mais cela fonctionnera.

7
adnan.

Ne pourriez-vous pas récupérer le schéma, supprimer la table et le recréer?

7
Nate

drop table devrait être le moyen le plus rapide de s'en débarrasser.

3
Paul Sonier

Tronquer est rapide, généralement de l'ordre de quelques secondes ou moins. Si cela prenait 30 minutes, il y avait probablement un cas de clé étrangère référençant la table que vous tronquiez. Il peut également y avoir des problèmes de verrouillage impliqués.

Tronquer est aussi efficace que l'on peut vider une table, mais vous devrez peut-être supprimer les références de clé étrangère, à moins que vous ne souhaitiez également que ces tables soient nettoyées.

1
Jeff Ferland

Avez-vous essayé d'utiliser "drop"? Je l'ai utilisé sur des tables de plus de 20 Go et il se termine toujours en quelques secondes.

1
Zenshai

Si vous voulez juste vous débarrasser complètement de la table, pourquoi ne pas simplement laisser tomber ça?

1
shylent

Nous avons eu ces problèmes. Nous n'utilisons plus la base de données en tant que magasin de session avec Rails 2.x et le magasin de cookies. Cependant, laisser tomber la table est une solution décente. Vous voudrez peut-être envisager d’arrêter le service mysql, de désactiver temporairement la journalisation, de démarrer en mode sans échec, puis de déposer/créer. Lorsque vous avez terminé, réactivez votre journalisation.

0
Brian Hogan

le réponse de searlea est Nice, mais comme indiqué dans les commentaires, vous perdez les clés étrangères pendant le combat .cette solution est similaire: le tronqué est exécuté en une seconde, mais vous conservez le clés. 

L'astuce consiste à désactiver/activer les contrôles FK.

SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE NewFoo LIKE Foo;
insert into NewFoo SELECT * from Foo where What_You_Want_To_Keep  

truncate table Foo;
insert into Foo SELECT * from NewFoo;
SET FOREIGN_KEY_CHECKS=1;

Réponse étendue - Supprimer tout sauf certaines lignes

Mon problème était le suivant: À cause d'un script fou, ma table était conçue pour 7.000.000 lignes indésirables. Je devais supprimer 99% des données de ce tableau, c’est pourquoi j’ai dû copier Ce que je veux conserver dans un tableau tmp avant de le supprimer.

Ces rangées de Foo que je devais conserver dépendaient d'autres tables, de clés étrangères et d'index.

quelque chose comme ca: 

insert into NewFoo SELECT * from Foo where ID in (
 SELECT distinct FooID from TableA 
 union SELECT distinct FooID from TableB 
 union SELECT distinct FooID from TableC
)

mais cette requête a toujours été dépassée après 1 heure . Donc, je devais le faire comme ceci:

CREATE TEMPORARY TABLE tmpFooIDS  ENGINE=MEMORY  AS (SELECT distinct FooID from TableA);
insert into tmpFooIDS SELECT distinct FooID from TableB
insert into tmpFooIDS SELECT distinct FooID from TableC
insert into NewFoo SELECT * from Foo where ID in (select ID from tmpFooIDS);

En théorie, comme les index sont correctement configurés, je pense que les deux méthodes de peuplement de NewFoo auraient dû être identiques, mais ce n’était pas le cas.

C'est pourquoi dans certains cas, vous pourriez faire comme ceci:

SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE NewFoo LIKE Foo;

-- Alternative way of keeping some data.
CREATE TEMPORARY TABLE tmpFooIDS  ENGINE=MEMORY  AS (SELECT * from Foo where What_You_Want_To_Keep);
insert into tmpFooIDS SELECT ID from Foo left join Bar where OtherStuff_You_Want_To_Keep_Using_Bar
insert into NewFoo SELECT * from Foo where ID in (select ID from tmpFooIDS);

truncate table Foo;
insert into Foo SELECT * from NewFoo;
SET FOREIGN_KEY_CHECKS=1;
0
Xavier

Je ne sais pas pourquoi ça prend si longtemps. Mais peut-être essayez-vous de renommer et de recréer un tableau vide. Ensuite, vous pouvez supprimer la table "extra" sans vous soucier du temps que cela prend. 

0
Brent Baisley