web-dev-qa-db-fra.com

InnoDB prend plus d'une heure pour importer un fichier de 600 Mo, MyISAM en quelques minutes

Je travaille actuellement sur la création d'un environnement pour tester les performances d'une application; Je teste avec MySQL et InnoDB pour savoir qui peut nous servir le mieux. Dans cet environnement, nous préparerons automatiquement la base de données (charger les vidages existants) et instrumenter nos outils de test.

Je me prépare à tester le même vidage de données avec MySQL et InnoDB, mais je n'arrive pas déjà à amener l'importation initiale à une vitesse utilisable pour la partie InnoDB. Le vidage initial a pris plus de temps, mais cela ne me concernait pas encore:

$ for i in testdb_myisam testdb_innodb; do time mysqldump --extended-insert $i > $i.sql; done

real    0m38.152s
user    0m8.381s
sys     0m2.612s

real    1m16.665s
user    0m6.600s
sys     0m2.552s

Cependant, les délais d'importation étaient assez différents:

$ for i in  testdb_myisam testdb_innodb; do time mysql $i < $i.sql; done

real    2m52.821s
user    0m10.505s
sys     0m1.252s

real    87m36.586s
user    0m10.637s
sys     0m1.208s

Après des recherches, je suis arrivé Changer les tables de MyISAM vers InnoDB rend le système lent puis j'ai utilisé set global innodb_flush_log_at_trx_commit=2:

$ time mysql testdb_innodb < testdb_innodb.sql

real    64m8.348s
user    0m10.533s
sys     0m1.152s

À mon humble avis, la vitesse est encore scandaleuse. J'ai également désactivé log_bin pour ces tests et voici une liste de toutes les variables mysql .

Dois-je accepter ces longs délais InnoDB ou peuvent-ils être améliorés? J'ai un contrôle total sur ce serveur MySQL car c'est uniquement pour cet environnement de test.

Je peux appliquer des configurations spéciales uniquement pour l'importation initiale et les modifier pour les tests d'applications afin qu'elles correspondent mieux aux environnements de production.

Mise à jour:

Compte tenu des commentaires, j'ai désactivé la validation automatique et les différents contrôles:

$ time ( echo "SET autocommit=0; SET unique_checks=0; SET foreign_key_checks=0;" \
; cat testdb_innodb.sql ; echo "COMMIT;" ) | mysql testdb_innodb;date

real    47m59.019s
user    0m10.665s
sys     0m2.896s

La vitesse s'est améliorée, mais pas tant que ça. Mon test est-il défectueux?

Mise à jour 2:

J'ai pu accéder à une autre machine où les importations n'ont pris que 8 minutes environ. J'ai comparé les configurations et appliqué les paramètres suivants à mon installation MySQL:

innodb_additional_mem_pool_size = 20971520
innodb_buffer_pool_size = 536870912
innodb_file_per_table
innodb_log_buffer_size = 8388608
join_buffer_size = 67104768
max_allowed_packet = 5241856
max_binlog_size = 1073741824
max_heap_table_size = 41943040
query_cache_limit = 10485760
query_cache_size = 157286400
read_buffer_size = 20967424
sort_buffer_size = 67108856
table_cache = 256
thread_cache_size = 128
thread_stack = 327680
tmp_table_size = 41943040

Avec ces paramètres, je suis maintenant à environ 25 minutes. Encore loin des quelques minutes que MyISAM prend, mais ça devient de plus en plus utilisable pour moi.

58
mark

Avez-vous essayé les Astuces de chargement de données en vrac des Astuces de réglage des performances InnoDB (en particulier le premier):

  • Lors de l'importation de données dans InnoDB, assurez-vous que MySQL n'a pas le mode autocommit activé car cela nécessite un vidage du journal sur le disque pour chaque insertion. Pour désactiver la validation automatique lors de votre opération d'importation, entourez-la de SET autocommit et COMMIT instructions:

    SET autocommit=0;
    ... SQL import statements ...
    COMMIT;
    

    Si vous utilisez l'option mysqldump --opt, vous obtenez des fichiers de vidage qui sont rapides à importer dans une table InnoDB, même sans les encapsuler avec le SET autocommit et COMMIT instructions.

  • Si vous avez des contraintes UNIQUE sur les clés secondaires, vous pouvez accélérer les importations de table en désactivant temporairement les vérifications d'unicité pendant la session d'importation:

    SET unique_checks=0;
    ... SQL import statements ...
    SET unique_checks=1;
    

    Pour les grandes tables, cela économise beaucoup d'E/S disque car InnoDB peut utiliser son tampon d'insertion pour écrire des enregistrements d'index secondaire dans un lot. Assurez-vous que les données ne contiennent aucune clé en double.

  • Si tu as FOREIGN KEY contraintes dans vos tables, vous pouvez accélérer les importations de table en désactivant les vérifications de clé étrangère pendant la durée de la session d'importation:

    SET foreign_key_checks=0;
    ... SQL import statements ...
    SET foreign_key_checks=1;
    

    Pour les grandes tables, cela peut économiser beaucoup d'E/S disque.

OMI, tout le chapitre mérite d'être lu.

129
Pascal Thivent

Avez-vous essayé de démarrer une transaction au début et de la valider à la fin? De la question que vous avez liée : "Modifiez l'étape Insérer des données pour démarrer une transaction au début et la valider à la fin. Vous obtiendrez une amélioration, je le garantir. "

N'oubliez pas qu'InnoDB est transactionnel, MyISAM ne l'est pas. Les moteurs transactionnels traitent chaque instruction comme une transaction individuelle si vous ne contrôlez pas explicitement la transaction. Cela peut être coûteux.

5
T.J. Crowder

J'ai trouvé que le disque dur était le goulot d'étranglement - les disques à l'ancienne sont sans espoir, le SSD est correct mais toujours loin d'être parfait. Importer vers tmpfs et copier les données est beaucoup plus rapide, détails: https://dba.stackexchange.com/a/89367/56667

2
egmont

J'ai rencontré des problèmes lors de l'importation en masse et je recommande la réponse acceptée. J'ai trouvé que vous pouvez également accélérer considérablement les choses en:

  1. Suppression de tous les index (autres que la clé primaire), chargement des données puis rajout d'index
  2. Vérification de votre innodb_log_file_size * innodb_log_files_in_group est suffisant pour éviter d'écrire sur le disque à une fréquence inférieure à la seconde

Concernant # 2, les valeurs par défaut de 5M * 2 ne suffiront pas sur un système moderne. Pour plus de détails, voir innodb_log_file_size et innodb_log_files_in_group

1
KCD