it-swarm-eu.dev

langsame Ladegeschwindigkeit von Daten aus mysqldump

Ich habe eine mittelgroße MySQL-Datenbank mit ungefähr 30 Tabellen, von denen einige 10 Millionen Datensätze sind, einige 100 Millionen. Das mysqldump aller Tabellen (in separate Dateien) ist ziemlich schnell und dauert etwa 20 Minuten. Es werden ungefähr 15 GB Daten generiert. Die größten gedumpten Dateien liegen im Bereich von 2 GB.

Wenn ich die Daten auf einer anderen Box, einem 8-GB-Computer mit sechs Kernen, in MySQL lade, dauert es ewig. Leicht 12 Stunden oder mehr.

Ich führe nur den MySQL-Client aus, um die Datei zu laden, d. H.

mysql database < footable.sql

direkt mit der Datei direkt aus mysqldump

mysqldump database foo > footable.sql

Offensichtlich mache ich etwas falsch. Wo fange ich an, damit es in angemessener Zeit endet?

Ich benutze weder am Dump noch an der Last Schalter.

21
Pat Farrell

Berücksichtigen Sie diese Punkte bei Ihrer Überlegung, sie können Ihnen beim Generieren und Wiederherstellen des Speicherauszugs helfen.

  1. Verwenden Sie Extended inserts In Dumps.
  2. Dump mit dem Format --tab, Damit Sie mysqlimport verwenden können, das schneller als mysql < dumpfile Ist.
  3. Importieren Sie mit mehreren Threads, einen für jede Tabelle.
  4. Verwenden Sie nach Möglichkeit ein anderes Datenbankmodul. Der Import in eine stark transaktionale Engine wie innodb ist furchtbar langsam. Das Einfügen in eine nicht-transaktionale Engine wie MyISAM ist viel schneller.
  5. Deaktivieren Sie Fremdschlüsselprüfungen und aktivieren Sie die automatische Festschreibung.
  6. Wenn Sie in innodb importieren, können Sie am effektivsten innodb_flush_log_at_trx_commit = 2 In Ihre my.cnf einfügen, während der Import vorübergehend ausgeführt wird. Sie können es auf 1 zurücksetzen, wenn Sie ACID benötigen

Versuche es..

22
Abdul Manaf

Ich habe in letzter Zeit viel damit zu tun. Sie können die Importleistung definitiv verbessern, indem Sie die Importe parallel ausführen. Der größte Teil der Verlangsamung basiert auf E/A, aber Sie können immer noch eine Verbesserung von 40% erzielen, indem Sie in Tabellen kopieren und diese dann mit jeweils 4 importieren.

Sie können dies mit Xargs wie folgt tun:

ls *.sql -1c | xargs -P4 -I tbl_name sh -c "mysql --user=username --password database < tbl_name"

wenn die Dateien vor dem Übertragen auf MySQL komprimiert werden, wird nichts verlangsamt, hauptsächlich aufgrund der verringerten E/A. Meine Tabellen wurden auf etwa 10: 1 komprimiert, wodurch viel Speicherplatz gespart wird.

Ich habe festgestellt, dass auf 4 Kerncomputern die Verwendung von 4 Prozessen optimal ist, wenn auch nur unwesentlich besser als die Verwendung von 3. Wenn Sie über SSDs oder ein schnelles RAID verfügen, werden Sie wahrscheinlich besser skalieren.

Einige andere Dinge zu beachten. Wenn Sie 4k-Sektor-Laufwerke haben, stellen Sie sicher, dass Sie key_cache_block_size=4096 Und myisam_block_size=4K Haben.

Wenn Sie MyISAM-Tabellen verwenden, setzen Sie myisam_repair_threads = 2 Oder höher. Auf diese Weise können Ihre zusätzlichen Kerne beim Wiederherstellen von Indizes helfen.

Stellen Sie sicher, dass Sie überhaupt nicht tauschen. Wenn ja, reduzieren Sie die Größe von innodb_buffer_pool_size.

Ich glaube, ich habe mit innnodb auch durch diese Optionen etwas beschleunigt:

innodb_flush_method= O_DIRECT (LINUX ONLY)
innodb_flush_log_at_commit = 0
innodb_doublewrite=0
innodb_support_xa=0
innodb_checksums=0

(Die letzten drei habe ich nicht ausgiebig getestet - ich glaube, ich habe sie als Vorschläge im Internet gefunden.) Beachten Sie, dass innodb_flush_log_at_commit=0 zu Beschädigungen führen kann, wenn MySQL abstürzt oder der Strom ausfällt.

7
greg

Zusätzlich zu Abdul's Antwort möchte ich die Wichtigkeit der --disable-keys Option, die Schlüssel ausschaltet, bis alle Daten für eine Tabelle geladen sind. Diese Option ist als Teil von --opt umschalten, der standardmäßig aktiviert ist, aber es wichtig fand, darauf hinzuweisen.

Wenn Sie während des Einfügens keine Schlüssel überspringen, wird der Index in jeder eingefügten Zeile neu erstellt. Ein extrem langsamer Prozess.

7
Derek Downey

Wenn Sie hauptsächlich MyISAM-Tabellen haben, sollten Sie Bulk Insert Buffer erhöhen. In der MySQL-Dokumentation wird Folgendes zum Setzen von massiven_insert_buffer_size angegeben:

MyISAM verwendet einen speziellen baumartigen Cache, um Masseneinfügungen für INSERT ... SELECT, INSERT ... VALUES (...), (...), ... und LOAD DATA INFILE zu beschleunigen, wenn Daten zu nicht leeren Daten hinzugefügt werden Tabellen. Diese Variable begrenzt die Größe des Cache-Baums in Bytes pro Thread. Wenn Sie den Wert auf 0 setzen, wird diese Optimierung deaktiviert. Der Standardwert ist 8 MB.

Es gibt zwei Dinge, die Sie tun müssen

1) Fügen Sie es zu /etc/my.cnf hinzu

[mysqld]
bulk_insert_buffer_size=512M

2) Stellen Sie den globalen Wert dafür ein

SET GLOBAL bulk_insert_buffer_size = 1024 * 1024 * 512;

Wenn Sie nicht über die Berechtigung verfügen ,ulk_insert_buffer_size global festzulegen, tun Sie dies

service mysql restart

Dies ist natürlich nicht für InnoDB.

Aus einem anderen Blickwinkel, unabhängig davon, ob es sich bei den Tabellen um InnoDB oder MyISAM handelt, haben Sie möglicherweise zu viele Indizes, wenn die Indizes größer als die Tabelle sind. Normalerweise gehe ich davon aus, dass ein Neuladen eines MyISAM mysqldump dreimal so lange dauern sollte wie der mysqldump. Ich gehe auch davon aus, dass ein Neuladen eines InnoDB-MySQL-Dumps viermal so lange dauern sollte, wie der MySQL-Dump benötigt hat.

Wenn Sie das Verhältnis 4: 1 zum Neuladen eines mysqldump überschreiten, haben Sie definitiv eines von zwei Problemen:

  • zu viele Indizes
  • indizes aufgrund großer Spalten einfach zu groß

Mit dieser Speicher-Engine können Sie die Größe Ihrer Daten messen:

SELECT IFNULL(B.engine,'Total') "Storage Engine",
CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Data Size", CONCAT(LPAD(REPLACE(
FORMAT(B.ISize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Index Size", CONCAT(LPAD(REPLACE(
FORMAT(B.TSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Table Size" FROM
(SELECT engine,SUM(data_length) DSize,SUM(index_length) ISize,
SUM(data_length+index_length) TSize FROM
information_schema.tables WHERE table_schema NOT IN
('mysql','information_schema','performance_schema') AND
engine IS NOT NULL GROUP BY engine WITH ROLLUP) B,
(SELECT 3 pw) A ORDER BY TSize;

Überprüfen Sie, ob die Indizes mindestens so groß wie die Daten oder sogar noch größer sind

Sie können die Binärprotokollierung auch folgendermaßen deaktivieren:

echo "SET SQL_LOG_BIN=0;" > footable.sql
mysqldump --databases foo >> footable.sql

vor dem erneuten Laden des Skripts

5
RolandoMySQLDBA

Wenn Sie das Dateisystem vollständig umgehen und die Ausgabe von mysqldump direkt in einen MySQL-Prozess leiten, sollten Sie spürbare Leistungsverbesserungen feststellen. Wie viel letztendlich davon abhängt, welche Art von Laufwerk Sie verwenden, aber ich verwende selten mehr Dump-Dateien, unabhängig von der Datenbankgröße, allein aus diesem Grund.

mysqldump -uxxx -pxxx -hxxx --single-transaction --routines --databases dbname | mysql -uyyy -pyyy -hyyy
2
Marcus Pope

Nach meinen Erfahrungen ist die Festplatte der Engpass. Vergessen Sie sich drehende Scheiben. SSD ist besser, aber bei weitem am besten ist es, dies in RAM - wenn Sie genug haben, um die gesamte Datenbank für eine kurze Zeit zu halten. Grob:

  1. hör auf mysqld
  2. verschieben Sie vorhandene Inhalte von/var/lib/mysql
  3. erstellen Sie ein leeres Verzeichnis/var/lib/mysql
  4. mount -t tmpfs -o size = 32g tmpfs/var/lib/mysql (Größe anpassen)
  5. erstellen Sie eine leere Datenbank (z. B. mysql_install_db, oder stellen Sie den vorherigen Inhalt wieder her.)
  6. starte mysqld
  7. importieren
  8. hör auf mysqld
  9. kopieren Sie/var/lib/mysql nach mysql2
  10. umount mysql; rmdir mysql
  11. verschiebe mysql2 nach mysql
  12. starte mysqld, sei glücklich

Für mich kann ein Speicherauszug von ~ 10G (/ var/lib/mysql, der ~ 20G verbraucht) in ungefähr 35 Minuten (mydumper/myloader), 45 Minuten (mysqldump --tab/mysqlimport), 50 Minuten (mysqldump/mysql) importiert werden. , auf einem 2x6-Kern 3,2 GHz Xeon.

Wenn Sie nicht genug RAM in einem einzelnen Computer) haben, aber mehrere Computer mit schnellem Netzwerk nebeneinander haben, wäre es interessant zu sehen, ob ihre RAMs mit nbd (Netzwerk) verbunden werden können Gerät blockieren). Oder mit innodb_file_per_table können Sie wahrscheinlich den obigen Vorgang für jede Tabelle wiederholen.

1
egmont