J'ai un suivi à ma question précédente concernant la vitesse d'importation avec Inno-Tables (surprise!).
Scénario
J'essaie d'importer un gros vidage de base de données * sur ma machine de développement locale dans un délai raisonnable. Nous avons beaucoup de KEY
attachés aux tables qui se sont avérés être un goulot d'étranglement mais qui sont toujours importants pour notre système en direct.
Mon approche après avoir posé la question ci-dessus était de supprimer les instructions KEY ...
Du vidage, d'importer et de rajouter des clés.
Cependant, je me retrouve souvent à modifier un vidage en cours pour l'importer localement et je suis tombé sur ces drôles de "commentaires" (les lignes disable/enable keys
)
--
-- Dumping data for table `monster`
--
LOCK TABLES `monster` WRITE;
/*!40000 ALTER TABLE `monster` DISABLE KEYS */;
INSERT … INSERT … INSERT
/*!40000 ALTER TABLE `monster` ENABLE KEYS */;
UNLOCK TABLES;
Mais en fait, ces "commentaires" sont des déclarations MySql conditionnelles
C'était une nouvelle pour moi mais ok, vu le formulaire de sortie mysql --version
Tout me va bien: mysql Ver 14.14 Distrib 5.5.38, for debian-linux-gnu (x86_64) using readline 6.3
Ce que je suppose
La table est verrouillée (très bien, c'est juste moi sur le dev mashine). Ensuite, les clés telles que définies dans le schéma de table sont désactivées, les données sont importées, les clés sont activées.
Ainsi, pendant la phase d'insertion de données, il ne devrait pas y avoir de perte de temps sur les clés, mais plutôt examiné après l'insertion de toutes les données.
Je penserais que c'est le même comportement que si je supprimais toutes les lignes KEY 'foo' (foo)'
- du vidage, importais le vidage et exécutais un script avec ADD KEY 'foo' ...
Par la suite.
Ce que j'observe
Il est beaucoup plus rapide de supprimer manuellement les clés, d'importer et de rajouter des clés, puis de s'appuyer sur des instructions conditionnelles DISABLE KEYS
Pour créer mes mysqldump
Édition manuelle du vidage + importation mysql + ajout de clés = 15 + 8 + 8 ≈ 30min
Importation simple de mysql: abandonné, (je suis juste payé pour 8 heures/jour> :))
Je ne peux pas m'empêcher de penser que je manque quelque chose de très fondamental ici (ou la base de données me traîne).
Vous ne pouvez pas compter sur DISABLE KEYS;
et ENABLE KEYS;
pour InnoDB car il n'est pas implémenté dans InnoDB Storage Engine. Fonctionnement ALTER TABLE ... DISABLE KEYS;
et ALTER TABLE ... ENABLE KEYS;
ont été conçus pour MyISAM. Comme il est dit dans la Documentation MySQL pour ALTER TABLE
:
Si vous utilisez ALTER TABLE sur une table MyISAM, tous les index non uniques sont créés dans un lot distinct (comme pour REPAIR TABLE). Cela devrait rendre ALTER TABLE beaucoup plus rapide lorsque vous avez plusieurs index.
Pour les tables MyISAM, la mise à jour des clés peut être contrôlée explicitement. Utilisez ALTER TABLE ... DISABLE KEYS pour dire à MySQL d'arrêter la mise à jour des index non uniques. Utilisez ensuite ALTER TABLE ... ENABLE KEYS pour recréer les index manquants. MyISAM le fait avec un algorithme spécial qui est beaucoup plus rapide que l'insertion de clés une par une, donc la désactivation des clés avant d'effectuer des opérations d'insertion en bloc devrait donner une accélération considérable. L'utilisation de ALTER TABLE ... DISABLE KEYS nécessite le privilège INDEX en plus des privilèges mentionnés précédemment.
Bien que les index non uniques soient désactivés, ils sont ignorés pour les instructions telles que SELECT et EXPLAIN qui autrement les utiliseraient.
Aucune mention n'est jamais faite d'InnoDB dans le contexte de ALTER TABLE ... DISABLE/ENABLE KEYS;
Même si vous exécutez ALTER TABLE ... DISABLE KEYS;
par rapport à une table InnoDB, il génère un avertissement:
mysql> show create table mytimes\G
*************************** 1. row ***************************
Table: mytimes
Create Table: CREATE TABLE `mytimes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`totalTime` int(11) NOT NULL,
`totalTimeDesc` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> alter table mytimes disable keys;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show warnings;
+-------+------+-------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------------+
| Note | 1031 | Table storage engine for 'mytimes' doesn't have this option |
+-------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
C'est pourquoi il n'y a aucun effet. Veuillez vous rappeler que @ jynus a mentionné la même chose dans sa réponse au point 7 .
Gardez également à l'esprit que MyISAM conserve les données et les index dans deux fichiers distincts (.MYD pour les données, .MYI pour les index), il serait donc trivial de désactiver et d'activer les index. InnoDB conserve la clé primaire et les données de ligne dans les mêmes pages InnoDB (via l'index clusterisé). Les index secondaires porteront la clé primaire comme pièce jointe à chaque entrée de feuille d'index secondaire . Étant donné que les données et les index sont entrelacés via l'index clusterisé, personne n'a encore tenté d'implémenter DISABLE KEYS
et ENABLE KEYS
dans InnoDB.