Ich habe ungefähr 40 Millionen Zeilen in einer MySQL-Tabelle und möchte diese Tabelle in eine andere Tabelle in derselben Datenbank kopieren. Was ist der effizienteste Weg, dies zu tun? Wie lange wird es dauern (ungefähr)?
Ich habe ungefähr 40 Millionen Zeilen in einer MySQL-Tabelle und möchte diese Tabelle in eine andere Tabelle in derselben Datenbank kopieren. Was ist der effizienteste Weg, dies zu tun? Wie lange wird es dauern (ungefähr)?
Antworten:
Angenommen, Sie haben mydb.mytb
und möchten erstellenmydb.mytbcopy
Ich habe fünf (5) Ansätze, um diese Kopie zu machen
Im mysql
Client den folgenden
USE mydb
CREATE TABLE mytbcopy LIKE mytb;
INSERT INTO mytbcopy SELECT * FROM mytb;
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysql ${MYSQL_CONN} -ANe"CREATE DATABASE IF NOT EXISTS test"
mysqldump ${MYSQL_CONN} mydb mytb | mysql ${MYSQL_CONN} -Dtest
mysql ${MYSQL_CONN} -ANe"ALTER TABLE test.mytb RENAME mydb.mytbcopy"
DUMPFILE=/some/path/tabledata.sql
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysql ${MYSQL_CONN} -ANe"CREATE DATABASE IF NOT EXISTS test"
mysqldump ${MYSQL_CONN} mydb mytb > ${DUMPFILE}
mysql ${MYSQL_CONN} -Dtest < ${DUMPFILE}
rm -f ${DUMPFILE}
mysql ${MYSQL_CONN} -ANe"ALTER TABLE test.mytb RENAME mydb.mytbcopy"
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysqldump ${MYSQL_CONN} mydb mytb | sed 's/mytb/mytbcopy' | mysql ${MYSQL_CONN} -Dmydb
DUMPFILE=/some/path/tabledata.sql
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysqldump ${MYSQL_CONN} mydb mytb | sed 's/mytb/mytbcopy' > ${DUMPFILE}
mysql ${MYSQL_CONN} -Dmydb < ${DUMPFILE}
rm -f ${DUMPFILE}
Wenn Sie mydb.mytb
in eine bereits vorhandene Tabelle kopieren möchten mydb.mytbcopy
und die beiden Tabellen identische Strukturen haben:
INSERT INTO mytbcopy SELECT * FROM mytb;
Wie #APPROACH 1 , #APPROACH 6 würde eine einzelne Transaktion von 40 Millionen Zeilen
MYSQL_USER=root
MYSQL_PASS=rootpassword
MYSQL_CONN="-u${MYSQL_USER} -p${MYSQL_PASS}"
mysqldump ${MYSQL_CONN} -t mydb mytb | sed 's/mytb/mytbcopy' | mysql ${MYSQL_CONN} -Dmydb
Dieser Ansatz lässt die Tabelle nicht fallen. Es werden einfach die INSERTs generiert
Ich kann Ihnen keine Zeitschätzung geben, da ich den Aufbau des DB-Servers, die Tabellenstruktur, das Indexlayout und ähnliches nicht kenne.
InnoDB-Tabellen können im Gegensatz zu MyISAM * nicht "einfach wegkopiert" werden, da sich ein Teil des Datenwörterbuchs (und möglicherweise anderer Strukturen, von denen die Tabelle abhängig ist, wie der Zusammenführungspuffer) im Arbeitsspeicher (wenn der Server ausgeführt wird) und in befindet Der Common / Main-Tablespace, auch bekannt als die große Datei, die aufgerufen wird ibdata1
.
Wenn Sie Percona Server> = 5.1 oder MySQL> = 5.6 verwenden, werden transportierbare Tablespaces unterstützt, mit denen Sie Tabellen direkt aus dem Dateisystem exportieren und importieren können. Hier ist es die Methode für MySQL und für Percona . In beiden Fällen ist es erforderlich, dass Sie die Tabelle mit der innodb_file_per_table
Option erstellt haben und die Verwendung von DISCARD TABLESPACE/IMPORT TABLESPACE
und / oder Percona Xtrabakup verwenden (wenn der Export online erfolgen soll). Bitte beachten Sie, dass Percona Server oder Xtrabakup nicht für Windows verfügbar sind.
Diese Methode ist im Allgemeinen so schnell wie das Kopieren der Datei mit den Dateisystembefehlen (cp, rsync).
Es kann zwar vorkommen, dass dies in MySQL <5.6 (auf eine hackige Art und Weise) für Wiederherstellungen funktioniert, bei einer Tabellenkopie funktioniert es jedoch nicht. In diesen Fällen können Sie SQL verwenden :
CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table SELECT * FROM old_table;
Dies ist so schnell, wie InnoDB ausgeführt werden kann, Handler_read_rnd_next
und zwar Handler_write
einmal pro Zeile. Wenn Sie diese Methode verwenden, stellen Sie sicher, dass Sie die Haltbarkeitsoptionen zumindest vorübergehend deaktivieren und über einen großen Pufferpool und ein Transaktionsprotokoll verfügen. Unter diesen Umständen kann es die Importzeit verkürzen, aber es passt definitiv nicht vollständig in den Speicher. Erwarten Sie also viel Zeit. Außerdem versuchen Sie, 40 Millionen Zeilen in eine einzelne Transaktion zu importieren, was zu Problemen führen kann.
Meine eigentliche Empfehlung in diesem zweiten Fall wäre, so etwas wie pt-archiver zu verwenden , da es eine Operation ausführt, die der gerade erwähnten ähnelt, aber in "Stücken" ausgeführt wird, wobei der Transaktionsaufwand vermieden wird (es könnte sein) nicht schneller sein, aber im Falle eines Fehlers wird nicht versucht, den gesamten Tisch rückgängig zu machen (ewig dauernd). Für die von Ihnen genannten Datengrößen ist dies wahrscheinlich der beste Weg.
Eine letzte Option wäre das Exportieren und Importieren im CSV- (oder TSV-) Format mit einer Kombination aus SELECT INTO OUTFILE / mysqldump und LOAD DATA / mysqlimport. Dies war eine sehr häufige Option, wenn Sie in bestimmten alten Versionen von mysql eine Parallelität benötigen, da mit sql größere Sperren erstellt wurden (nicht mehr wahr, wenn dies korrekt durchgeführt wurde). Da mysqldump / import nur serialisiert funktioniert, würde ich Ihnen empfehlen, nach Optionen zu suchen, um es zu parallelisieren. Dies ist sehr nützlich für große Tabellen.
Vermeiden Sie auf jeden Fall mehrere SQL-Sätze, da dies Ihr wichtigster Engpass ist, wenn Sie viele verschiedene Abfragen ausführen (die einzeln ausgeführt, analysiert und optimiert werden müssen).
* MyISAM-Strukturen können nicht im laufenden Betrieb kopiert werden, es ist jedoch sehr einfach, sie vorübergehend auf die Festplatte zu synchronisieren FTWRL
.
Verschieben von Daten von einer Tabelle in eine andere im Schema
create table your_table_name select * from old_schema_table;