Je suis un parent novice quand il s'agit de bases de données. Nous utilisons MySQL et je suis en train d'essayer d'accélérer le rythme d'une instruction SQL qui semble prendre un certain temps à s'exécuter. J'ai regardé autour de sur DONC pour une question similaire, mais n'en trouvait pas.
L'objectif est de supprimer toutes les lignes dans Une table qui ont un id correspondant dans le tableau B.
Je suis actuellement en train de faire le suivant:
DELETE FROM a WHERE EXISTS (SELECT b.id FROM b WHERE b.id = a.id);
Il y a environ 100K lignes dans une table et environ 22K lignes dans la table b. La colonne " id " est la PK pour les deux tableaux.
Cette déclaration prend environ 3 minutes pour s'exécuter sur mon test de box - Pentium D, XP SP3, 2 go de ram, MySQL 5.0.67. Cela semble lent à moi. Peut-être qu'il ne l'est pas, mais j'espérais pour accélérer les choses. Est-il mieux/plus rapide façon d'accomplir cette?
EDIT:
Quelques informations supplémentaires qui pourraient être utiles. Les tableaux A et B ont la même structure que j'ai effectué les opérations suivantes pour créer la table B:
CREATE TABLE b LIKE a;
Le tableau a (et donc de la table b) a quelques indices pour aider à accélérer les requêtes qui sont portées contre elle. Encore une fois, je suis un novice par rapport à la DB de travail et toujours en apprentissage. Je ne sais pas quel effet, le cas échéant, cela a sur les choses. Je suppose qu'il n'ont un effet que l'index doivent être nettoyés trop, non? Je me demandais aussi si il y avait d'autres DB paramètres qui peuvent affecter la vitesse.
Aussi, je suis en utilisant INNO DB.
Voici quelques informations supplémentaires qui pourraient vous être utiles.
La Table a une structure similaire à ceci (j'ai désinfecté cela un peu):
DROP TABLE IF EXISTS `frobozz`.`a`;
CREATE TABLE `frobozz`.`a` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`fk_g` varchar(30) NOT NULL,
`h` int(10) unsigned default NULL,
`i` longtext,
`j` bigint(20) NOT NULL,
`k` bigint(20) default NULL,
`l` varchar(45) NOT NULL,
`m` int(10) unsigned default NULL,
`n` varchar(20) default NULL,
`o` bigint(20) NOT NULL,
`p` tinyint(1) NOT NULL,
PRIMARY KEY USING BTREE (`id`),
KEY `idx_l` (`l`),
KEY `idx_h` USING BTREE (`h`),
KEY `idx_m` USING BTREE (`m`),
KEY `idx_fk_g` USING BTREE (`fk_g`),
KEY `fk_g_frobozz` (`id`,`fk_g`),
CONSTRAINT `fk_g_frobozz` FOREIGN KEY (`fk_g`) REFERENCES `frotz` (`g`)
) ENGINE=InnoDB AUTO_INCREMENT=179369 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
Je soupçonne qu'une partie de la question est qu'il ya un certain nombre d'indices de cette table.
Tableau B ressemble à la table B, mais il ne contient les colonnes id
et h
.
Aussi, le profilage résultats sont comme suit:
starting 0.000018
checking query cache for query 0.000044
checking permissions 0.000005
Opening tables 0.000009
init 0.000019
optimizing 0.000004
executing 0.000043
end 0.000005
end 0.000002
query end 0.000003
freeing items 0.000007
logging slow query 0.000002
cleaning up 0.000002
RÉSOLU
Merci pour toutes les réponses et commentaires. Ils ont certainement m'a fait réfléchir sur le problème. Bravo à dotjoe pour m'éloigner du problème en posant la simple question "d'autres tables de référence une.id?"
Le problème est qu'il y a un DÉCLENCHEUR de SUPPRESSION sur la table Un qui appelle une procédure stockée de mettre à jour deux autres tables, C et D. le Tableau C avait une FK retour à un.id et après avoir fait quelques trucs liés à ce code dans la procédure stockée, il avait de l'instruction,
DELETE FROM c WHERE c.id = theId;
J'ai regardé dans l'EXPLIQUER déclaration et a réécrit ce que,
EXPLAIN SELECT * FROM c WHERE c.other_id = 12345;
Donc, je ne pouvais voir ce qu'il faisait et il m'a donné les informations suivantes:
id 1
select_type SIMPLE
table c
type ALL
possible_keys NULL
key NULL
key_len NULL
ref NULL
rows 2633
Extra using where
Ceci m'a dit que c'était une douloureuse opération à faire et comme il allait être appelé 22500 fois (pour l'ensemble de données sont supprimées), qui était le problème. Une fois que j'ai créé un INDEX sur cette other_id colonne et rediffusé l'EXPLIQUER, j'ai eu:
id 1
select_type SIMPLE
table c
type ref
possible_keys Index_1
key Index_1
key_len 8
ref const
rows 1
Extra
Beaucoup mieux, en fait, vraiment génial.
J'ai ajouté que Index_1 et mon supprimer les heures sont en ligne avec les temps déclarés par mattkemp. Ce fut un très subtile erreur de ma part en raison de la chaussure horning certaines fonctionnalités supplémentaires à la dernière minute. Il s'est avéré que la plupart de l'alternative proposée SUPPRIMER/SELECT, comme Daniel l'a déclaré, a fini par prendre essentiellement la même quantité de temps et que soulmerge mentionné, la déclaration a été à peu près le meilleur que j'allais être capable de construire fondé sur ce que je devais faire. Une fois que j'ai fourni un indice pour cet autre tableau C, mon Suppressions ont été rapides.
Post-mortem:
Deux leçons apprises au cours de cet exercice. Tout d'abord, il est clair que je n'ai pas de tirer parti de la puissance de l'EXPLIQUER pour obtenir une meilleure idée de l'impact de mes requêtes SQL. C'est une erreur de débutant, donc je ne vais pas me battre jusqu'à ce propos. Je vais apprendre de cette erreur. Deuxièmement, le code malveillant a été le résultat d'un "get it done quick" mentalité et l'insuffisance de conception, de test a conduit à ce problème ne se présente plus tôt. J'avait généré plusieurs grandes ensembles de données de test à utiliser comme entrée de test pour cette nouvelle fonctionnalité, je n'aurais pas perdu mon temps ni la vôtre. Mes tests sur la DB côté manquait de la profondeur de mon côté a mis en place. Maintenant, j'ai eu l'occasion de l'améliorer.