web-dev-qa-db-de.com

geschwindigkeit beim Mysql-Import verbessern

Ich habe eine große Datenbank von 22GB. Ich habe ein Backup mit dem Befehl mysqldump im gzip-Format erstellt. 

Wenn ich die gz-Datei extrahiere, wird die .sql-Datei von 16.2GB erzeugt.

Wenn ich versuche, die Datenbank auf meinem lokalen Server zu importieren, dauert der Import ungefähr 48 Stunden. Gibt es eine Möglichkeit, den Importvorgang zu beschleunigen? 

Außerdem würde ich gerne wissen, ob Änderungen an der Hardware vorgenommen werden müssen, um die Leistung zu verbessern.

Aktuelle Systemkonfiguration

 Processor: 4th Gen i5
 RAM: 8GB

#update

my.cnf lautet wie folgt

#
# 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/

Es wird gerade für 3 Tage hochgeladen und 9,9 GB wurden gerade importiert. Die Datenbank verfügt über MyISAM- und InnoDB-Tabellen. Was kann ich tun, um die Importleistung zu verbessern?

Ich habe versucht, jede Tabelle separat im gz-Format mit mysqldump zu exportieren und jede Tabelle über das Skript PHP zu importieren, das folgenden Code ausführt

$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

Es fehlen viele Parameter, um die Ursache des Problems vollständig zu verstehen. sowie:

  1. MySQL-Version
  2. Festplattentyp und Geschwindigkeit
  3. Geben Sie auf dem Server Speicher frei, bevor Sie den MySQL-Server starten
  4. iostat-Ausgabe vor und zum Zeitpunkt des mysqldump. 
  5. Welche Parameter verwenden Sie zum Erstellen der Speicherauszugsdatei?.

und viele mehr.

Ich versuche also zu erraten, dass Ihr Problem in den Festplatten liegt, da ich 150 Instanzen von MySQL habe, die ich mit 3 TB Daten auf einer von ihnen verwalte. Normalerweise ist die Festplatte das Problem

Nun zur Lösung:

Vor allem - Ihr MySQL ist nicht für beste Leistung konfiguriert.

Informationen zu den wichtigsten Einstellungen, die Sie im Percona-Blogeintrag konfigurieren können, finden Sie unter: http://www.percona.com/blog/2014/01/28/10-mysql-settings-to-tune-after- Installation/

Überprüfen Sie insbesondere die Parameter:

innodb_buffer_pool_size 
innodb_flush_log_at_trx_commit
innodb_flush_method

Wenn Ihr Problem darin besteht, dass die Festplatte - das Lesen der Datei von demselben Laufwerk - das Problem noch verschlimmert. 

Wenn Ihr MySQL-Server beginnt zu tauschen, weil nicht genügend RAM verfügbar ist, wird Ihr Problem noch größer.

Sie müssen vor und zum Zeitpunkt des Wiederherstellungsvorgangs eine Diagnose auf Ihrem Computer ausführen, um dies herauszufinden.

Darüber hinaus kann ich Ihnen vorschlagen, eine andere Technik zur Durchführung der Neuerstellungsaufgabe zu verwenden, die schneller als mysqldump funktioniert.

Es ist Percona Xtrabackup - http://www.percona.com/doc/percona-xtrabackup/2.2/

Sie müssen das Backup damit erstellen und von dort wiederherstellen oder den Server mit Streaming-Option direkt neu erstellen.

MySQL-Version ab 5.5 - InnoDB ist schneller als MyISAM. Erwägen Sie, alle Ihre Tabellen darauf zu ändern.

10
Tata

Wenn Sie in der beschriebenen Weise einen Dump erstellen und wiederherstellen, bedeutet dies, dass MySQL die Indizes vollständig neu erstellen muss, während die Daten importiert werden. Es muss auch die Daten jedes Mal analysieren. 

Es wäre viel effizienter, wenn Sie Datendateien in einem Format kopieren könnten, das MySQL bereits versteht. Ein guter Weg, dies zu tun, ist die Verwendung von innobackupex von Percona 

(Open Source und als Teil von XtraBackup verfügbar zum Download von hier ).

Dadurch wird eine Momentaufnahme der MyISAM-Tabellen erstellt. Bei InnoDB-Tabellen werden die zugrunde liegenden Dateien kopiert. Anschließend wird das Transaktionsprotokoll mit ihnen abgespielt, um einen konsistenten Status sicherzustellen. Dies kann von einem Live-Server ohne Ausfallzeiten ausgeführt werden (ich habe keine Ahnung, ob dies eine Anforderung von Ihnen ist?)

Ich schlage vor, dass Sie die Dokumentation lesen, aber um ein Backup in seiner einfachsten Form zu erstellen, verwenden Sie:

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

Wenn sich die Daten auf demselben Computer befinden, hat innobackupex sogar einen einfachen Wiederherstellungsbefehl:

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

Es gibt viele weitere Optionen und verschiedene Möglichkeiten, das Backup tatsächlich durchzuführen. Ich möchte Sie daher dazu ermutigen, sich die Dokumentation gut durchzulesen, bevor Sie beginnen.

Unser langsamer Testserver, der etwa 600 IOPS ausführt, kann mit dieser Methode innerhalb von etwa 4 Stunden eine 500-GB-Sicherung wiederherstellen.

Zum Schluss: Sie haben erwähnt, was getan werden könnte, um den Import zu beschleunigen. Es hängt hauptsächlich davon ab, was der Flaschenhals ist. In der Regel sind Importvorgänge E/A-gebunden (Sie können dies testen, indem Sie nach io-Wartezeiten suchen). Die Beschleunigung erfolgt durch einen schnelleren Datenträger-Durchsatz - entweder schnellere Datenträger selbst oder mehr davon gleichzeitig.

11
AndySavage

Eine Sache, die Sie tun können, ist

SET AUTOCOMMIT = 0; SET FOREIGN_KEY_CHECKS=0

Und Sie können auch mit den Werten spielen

innodb_buffer_pool_size
innodb_additional_mem_pool_size
innodb_flush_method

in my.cnf, um Sie zum Laufen zu bringen, aber im Allgemeinen sollten Sie einen Blick auf die Parameter rest of innodb werfen, um zu sehen, was am besten zu Ihnen passt.

Dies ist ein Problem, das ich in der Vergangenheit hatte. Ich habe nicht das Gefühl, dass ich mich vollständig angepackt habe, aber ich hoffe, ich hatte mich von Anfang an in diese Richtung gezeigt. Hätte mir einige Zeit gespart.

5
fakedrake

Stellen Sie sicher, dass Sie Ihre Variable " max_allowed_packet " auf eine ausreichende Größe erhöhen. Dies ist wirklich hilfreich, wenn Sie viele Textdaten haben. Die Verwendung von Hochleistungshardware wird die Geschwindigkeit beim Importieren von Daten sicherlich verbessern.

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

Holen Sie sich mehr RAM, einen schnelleren Prozessor und eine SSD für schnellere Schreibvorgänge. Batch die Einsätze, so dass sie schneller als eine Reihe einzelner Einsätze laufen. Es ist eine riesige Datei und wird Zeit brauchen. 

2
holtc

Möglichkeit 1: Deaktivieren Sie die Fremdschlüssel, wie von Fakedrake vorgeschlagen.

SET AUTOCOMMIT = 0; SET FOREIGN_KEY_CHECKS = 0

Methode 2: Verwenden Sie BigDump, um Ihre mysqldump-Datei zu zerlegen und diese dann zu importieren. http://www.ozerov.de/bigdump/usage/

Frage: Sie haben gesagt, dass Sie hochladen? Wie importieren Sie Ihren Dump? nicht direkt vom Server/Kommandozeile?

2
Vivek

Ich musste mich mit dem gleichen Problem befassen. Ich habe festgestellt, dass mysqldump für die Ausgabe in eine CSV-Datei (wie folgt) verwendet wurde:

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

und importieren Sie dann diese Daten mithilfe der LOAD DATA INFILE-Abfrage aus dem mysql-Client (wie folgt):

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

etwa um eine Größenordnung schneller als nur die SQL-Abfragen auszuführen, die die Daten enthalten. Natürlich hängt es auch davon ab, dass die Tabellen bereits erstellt werden (und leer sind).

Sie können dies natürlich auch tun, indem Sie zuerst Ihr leeres Schema exportieren und dann importieren.

2
Vinbot

Ich bin nicht sicher, ob dies eine Option für Sie ist, aber der beste Weg, dies zu tun, ist das, was Tata und AndySavage bereits gesagt haben: Erstellen Sie einen Schnappschuss der Datendateien vom Produktionsserver und installieren Sie sie mit Perconas auf Ihrer lokalen Box Innobackupex. Es werden InnoDb-Tabellen auf konsistente Weise gesichert und eine Schreibsperre für MyISAM-Tabellen ausgeführt. 

Bereiten Sie eine vollständige Sicherung auf der Produktionsmaschine vor:

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

Kopieren Sie die gesicherten Dateien (oder leiten Sie sie über SSH während des Backups - mehr Infos hier ) auf Ihren lokalen Rechner und stellen Sie sie wieder her:

Wiederherstellen der Sicherung:

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

Die vollständige Dokumentation zu innobackupex finden Sie hier: http://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/innobackupex_script.html

Die Wiederherstellungszeit ist VIEL schneller als das Lesen eines SQL-Dumps.

0
Diego