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.
Berücksichtigen Sie diese Punkte bei Ihrer Überlegung, sie können Ihnen beim Generieren und Wiederherstellen des Speicherauszugs helfen.
Extended inserts
In Dumps.--tab
, Damit Sie mysqlimport
verwenden können, das schneller als mysql < dumpfile
Ist.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ötigenVersuche es..
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.
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.
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:
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
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
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:
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.