web-dev-qa-db-fra.com

améliorer la vitesse d'importation mysql

J'ai une grande base de données de 22GB. J'avais l'habitude de faire une sauvegarde avec la commande mysqldump au format gzip. 

Quand j'extrais le fichier gz, il produit le fichier .sql de 16.2GB

Lorsque j'essaie d'importer la base de données sur mon serveur local, il faut environ 48 heures pour l'importer. Existe-t-il un moyen d'augmenter la vitesse du processus d'importation? 

Aussi, j'aimerais savoir si des modifications matérielles doivent être apportées pour améliorer les performances.

Configuration système actuelle

 Processor: 4th Gen i5
 RAM: 8GB

#mettre à jour

mon.cnf est comme suit

#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
# 
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

# Here is entries for some specific programs
# The following values assume you have at least 32M ram

# This was formally known as [safe_mysqld]. Both versions are currently parsed.
[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
Nice        = 0

[mysqld]
#
# * Basic Settings
#
user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port        = 3306
basedir     = /usr
datadir     = /var/lib/mysql
tmpdir      = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address        = 127.0.0.1
#
# * Fine Tuning
#
key_buffer      = 16M
max_allowed_packet  = 512M
thread_stack        = 192K
thread_cache_size       = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover         = BACKUP
#max_connections        = 100
#table_cache            = 64
#thread_concurrency     = 10
#
# * Query Cache Configuration
#
query_cache_limit   = 4M
query_cache_size        = 512M
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file        = /var/log/mysql/mysql.log
#general_log             = 1
#
# Error log - should be very few entries.
#
log_error = /var/log/mysql/error.log
#
# Here you can see queries with especially long duration
#log_slow_queries   = /var/log/mysql/mysql-slow.log
#long_query_time = 2
#log-queries-not-using-indexes
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
#       other settings you may need to change.
#server-id      = 1
#log_bin            = /var/log/mysql/mysql-bin.log
expire_logs_days    = 10
max_binlog_size         = 100M
#binlog_do_db       = include_database_name
#binlog_ignore_db   = include_database_name
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem



[mysqldump]
quick
quote-names
max_allowed_packet  = 512M

[mysql]
#no-auto-rehash # faster start of mysql but no tab completition

[isamchk]
key_buffer      = 512M

#
# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/mysql/conf.d/

Le téléchargement dure depuis 3 jours et 9,9 Go ont été importés. La base de données contient les tables MyISAM et InnoDB. Que puis-je faire pour améliorer les performances d'importation?

J'ai essayé d'exporter chaque table séparément au format gz avec mysqldump et d'importer chaque table via le script PHP en exécutant le code suivant

$dir="./";
$files = scandir($dir, 1);
array_pop($files);
array_pop($files);
$tablecount=0;
foreach($files as $file){
    $tablecount++;
    echo $tablecount."     ";

    echo $file."\n";
    $command="gunzip < ".$file." | mysql -u root -pubuntu cms";

    echo exec($command);
}
43
DharanBro

Il manque beaucoup de paramètres pour bien comprendre la raison du problème. tel que:

  1. Version de MySQL
  2. Type de disque et vitesse
  3. Libérez de la mémoire sur le serveur avant de démarrer le serveur MySQL
  4. sortie iostat avant et au moment de mysqldump. 
  5. Quels sont les paramètres que vous utilisez pour créer le fichier de vidage en premier lieu.

et beaucoup plus.

Je vais donc essayer de deviner que votre problème se situe au niveau des disques, car j’ai 150 instances de MySQL que je gère avec 3 To de données sur l’une d’entre elles, et le problème vient généralement du disque.

Maintenant à la solution:

Tout d’abord, votre MySQL n’est pas configuré pour offrir les meilleures performances.

Vous trouverez des informations sur les principaux paramètres à configurer sur le billet de blog Percona: http://www.percona.com/blog/2014/01/28/10-mysql-settings-to-tune-after- installation/

Vérifiez en particulier les paramètres:

innodb_buffer_pool_size 
innodb_flush_log_at_trx_commit
innodb_flush_method

Si votre problème est le disque - lire le fichier à partir du même lecteur - aggrave le problème. 

Et si votre serveur MySQL commence à échanger car il ne dispose pas de suffisamment de mémoire RAM - votre problème devient encore plus grave.

Vous devez exécuter des diagnostics sur votre ordinateur avant et au moment de la procédure de restauration pour le savoir.

De plus, je peux vous suggérer d'utiliser une autre technique pour effectuer la tâche de reconstruction, qui fonctionne plus rapidement que mysqldump.

C'est Percona Xtrabackup - http://www.percona.com/doc/percona-xtrabackup/2.2/

Vous devrez créer la sauvegarde avec celle-ci et la restaurer, ou reconstruire à partir du serveur en cours d'exécution directement avec l'option de diffusion en continu.

De plus, la version MySQL à partir de la version 5.5 - InnoDB est plus rapide que MyISAM. Pensez à changer toutes vos tables pour cela.

10
Tata

Effectuer une sauvegarde et une restauration de la manière décrite signifiera que MySQL devra reconstruire complètement les index lors de l’importation des données. Il doit également analyser les données à chaque fois. 

Il serait beaucoup plus efficace de copier les fichiers de données dans un format que MySQL comprend déjà. Pour ce faire, utilisez innobackupex de Percona 

(Open Source et distribué dans XtraBackup disponible au téléchargement depuis ici ).

Cela prend un instantané des tables MyISAM et, pour les tables InnoDB, il copie les fichiers sous-jacents, puis rejoue le journal des transactions sur ces tables pour assurer un état cohérent. Il peut le faire à partir d’un serveur en direct sans temps d’arrêt (je ne sais pas s’il s’agit d’une exigence de votre part?)

Je vous suggère de lire la documentation, mais pour faire une sauvegarde sous sa forme la plus simple, utilisez:

$ innobackupex --user=DBUSER --password=DBUSERPASS /path/to/BACKUP-DIR/
$ innobackupex --apply-log /path/to/BACKUP-DIR/

Si les données se trouvent sur le même ordinateur, innobackupex propose même une simple commande de restauration:

$ innobackupex --copy-back /path/to/BACKUP-DIR

Il y a beaucoup plus d'options et de façons différentes de faire la sauvegarde, je vous encourage donc à lire attentivement la documentation avant de commencer.

Pour des raisons de rapidité, notre serveur de test lent, qui traite environ 600 IOPS, peut restaurer une sauvegarde de 500 Go en environ 4 heures avec cette méthode.

Enfin: vous avez mentionné ce qui pourrait être fait pour accélérer l’importation. Cela dépendra principalement de ce qu'est le goulot d'étranglement. En règle générale, les opérations d'importation sont liées aux E/S (vous pouvez le vérifier en vérifiant les io attentes) et l'accélération consiste à accélérer le débit du disque - soit des disques plus rapides eux-mêmes, soit plusieurs à l'unisson.

11
AndySavage

Une chose que vous pouvez faire est

SET AUTOCOMMIT = 0; SET FOREIGN_KEY_CHECKS=0

Et vous pouvez aussi jouer avec les valeurs

innodb_buffer_pool_size
innodb_additional_mem_pool_size
innodb_flush_method

dans my.cnf pour vous lancer, mais en général, vous devriez jeter un coup d'œil au reste des paramètres innodb ainsi que pour voir ce qui vous convient le mieux.

C’est un problème que j’ai eu par le passé, j’ai le sentiment que je n’ai pas complètement abordé la question, mais j’espère avoir pris cette direction dès le départ. Me serait épargné pas mal de temps.

5
fakedrake

Assurez-vous d’augmenter la taille de votre variable " max_allowed_packet ". Cela vous aidera vraiment si vous avez beaucoup de données textuelles. L'utilisation de matériel haute performance accélérera sûrement la vitesse d'importation des données.

mysql --max_allowed_packet=256M -u root -p < "database-file.sql"
4
koolkoda

Obtenez plus de RAM, obtenez un processeur plus rapide, procurez-vous un SSD pour des écritures plus rapides. Batch les inserts afin qu'ils courent plus vite qu'un tas d'inserts individuels. C'est un fichier énorme, et cela prendra du temps. 

2
holtc

Méthode 1: désactivez les clés étrangères comme suggéré par fakedrake. 

SET AUTOCOMMIT = 0; SET FOREIGN_KEY_CHECKS = 0

Voie 2: Utilisez BigDump, il coupera votre fichier mysqldump, puis importera cela . http://www.ozerov.de/bigdump/usage/

Question: Vous avez dit que vous mettez en ligne? comment vous importez votre dump? pas directement à partir du serveur/ligne de commande?

2
Vivek

J'ai eu à traiter le même problème. J'ai trouvé l'utilisation de mysqldump pour générer un fichier CSV (comme celui-ci):

mysqldump -u [username] -p -t -T/path/to/db/directory [database] --fields-enclosed-by=\" --fields-terminated-by=,

et ensuite importer ces données en utilisant la requête LOAD DATA INFILE depuis le client mysql (comme ceci):

LOAD DATA FROM INFILE /path/to/db/directory/table.csv INTO TABLE FIELDS TERMINATED BY ',';

d’être d’un ordre de grandeur plus rapide que l’exécution des requêtes SQL contenant les données. Bien sûr, cela dépend aussi des tables déjà créées (et vides).

Vous pouvez également le faire en exportant puis en important votre schéma vide.

2
Vinbot

Je ne suis pas sûr que ce soit une option pour vous, mais la meilleure façon de procéder est ce que Tata et AndySavage ont déjà dit: prendre un instantané des fichiers de données à partir du serveur de production puis les installer sur votre ordinateur local en utilisant ceux de Percona. innobackupex. Il sauvegardera les tables InnoDb de manière cohérente et effectuera un verrouillage en écriture sur les tables MyISAM. 

Préparez une sauvegarde complète sur la machine de production:

http://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/preparing_a_backup_ibk.html

Copiez (ou dirigez via SSH lors de la sauvegarde - plus d'infos ici ) les fichiers sauvegardés sur votre ordinateur local et restaurez-les:

Restaurez la sauvegarde:

http://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/restoring_a_backup_ibk.html

Vous trouverez la documentation complète d’innobackupex ici: http://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/innobackupex_script.html

Le temps de restauration sera BEAUCOUP plus rapide que la lecture d'un cliché SQL.

0
Diego