web-dev-qa-db-fra.com

Copier d'une table MySQL vers une autre table MySQL de la même base de données

J'ai environ 40 millions de lignes dans une table MySQL et je veux copier cette table dans une autre table de la même base de données. Quelle est la manière la plus efficace de procéder? Combien de temps cela prendra-t-il (environ)?

15
Devashish Dixit

Supposons que vous ayez mydb.mytb et vous voulez créer mydb.mytbcopy

J'ai cinq (5) approches pour faire cette copie

APPROCHE # 1

Dans le client mysql, exécutez ce qui suit

USE mydb
CREATE TABLE mytbcopy LIKE mytb;
INSERT INTO mytbcopy SELECT * FROM mytb;

APPROCHE # 2

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"

APPROCHE # 3

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"

APPROCHE # 4

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

APPROCHE # 5

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}

UNE ANALYSE

  • L'APPROCHE # 1 est la plus simple en termes d'étapes, mais nécessite de pousser 40 millions de lignes en une seule transaction. Ce sera le plus lourd sur le moteur de stockage InnoDB.
  • Pour les autres approches, mysqldump enverra 40 millions de lignes en mandrins de milliers de lignes
    • APPROACH # 2 and APPROACH # 3 mysqldump la table dans le test base de données. Après avoir créé la table dans la base de données de test, elle est ensuite renommée et déplacée dans la base de données d'origine
    • APPROCHE # 4 et APPROCHE # 5 renommez la table en utilisant sed contre le flux provenant de mysqldump car il fait écho aux commandes INSERT
    • APPROCHE # 2 et APPROCHE # 4 utilise des canaux au lieu d'un fichier de sortie
    • APPROCHE # 3 et APPROCHE # 5 utilise un fichier de sortie pour un rechargement ultérieur

Si vous souhaitez copier mydb.mytb vers une table déjà existante mydb.mytbcopy, et les deux tables ont des structures identiques:

APPROCHE # 6

INSERT INTO mytbcopy SELECT * FROM mytb;

Comme # APPROCHE 1 , # APPROCHE 6 aurait une seule transaction de 40 millions de lignes

APPROCHE # 7

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

Cette approche ne laisse pas tomber le tableau. Il génère simplement les INSERT

ÉPILOGUE

Je ne peux pas vous donner d'estimation de temps car je ne connais pas la composition du serveur DB, la structure de la table, la disposition des index et des choses comme celles-ci.

ESSAIE !!!

23
RolandoMySQLDBA

Les tables InnoDB, contrairement à MyISAM *, ne peuvent pas être "simplement copiées", car une partie de son dictionnaire de données (et potentiellement d'autres structures dont la table dépend, comme le tampon de fusion) sont situées en mémoire (si le serveur est en cours d'exécution) et dans l'espace de table commun/principal, alias ce gros fichier appelé ibdata1.

Si vous utilisez Percona Server> = 5.1 ou MySQL> = 5.6, les espaces de table transportables sont pris en charge, ce qui vous permet d'exporter et d'importer des tableaux directement à partir du système de fichiers. Voici la méthode pour MySQL et pour Percona . Dans les deux cas, vous devez avoir créé la table avec le innodb_file_per_table option et implique l'utilisation de DISCARD TABLESPACE/IMPORT TABLESPACE et/ou Percona Xtrabakup (si vous souhaitez que l'exportation se fasse en ligne). Veuillez noter que Percona Server ou Xtrabakup ne sont pas disponibles pour Windows.

Cette méthode sera, parlant en général, aussi rapide que la copie du fichier en utilisant les commandes du système de fichiers (cp, rsync).

Bien qu'il puisse y avoir des cas où cela pourrait fonctionner dans MySQL <5.6 (de manière hacky) pour les restaurations, cela ne fonctionnera pas pour une copie de table. Dans ces cas, une façon de le faire est d'utiliser SQL :

CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table SELECT * FROM old_table;

Ce sera aussi rapide que InnoDB peut exécuter Handler_read_rnd_next et Handler_write, une fois par ligne. Si vous utilisez cette méthode, assurez-vous que vous désactivez, au moins temporairement, les options de durabilité et que vous disposez d'un grand pool de mémoire tampon et d'un journal des transactions. Dans ces circonstances, cela peut réduire le temps d'importation, mais il ne rentrera certainement pas dans la mémoire, alors attendez-vous beaucoup de temps. En outre, vous essayez d'importer 40 millions de lignes en une seule transaction, ce qui peut entraîner des problèmes.

Ma recommandation réelle, dans ce deuxième cas, serait d'utiliser quelque chose comme pt-archiver, car il effectuera une opération similaire à celui que je viens de mentionner, mais cela se fera en "morceaux", en évitant les frais généraux transactionnels (ce ne sera peut-être pas plus rapide, mais en cas d'échec, il n'essaiera pas de faire reculer toute la table, prenant une éternité ). Pour les tailles de données que vous mentionnez, c'est probablement la meilleure façon de procéder.

Une dernière option serait d'exporter et d'importer en utilisant le format CSV (ou TSV) , avec une combinaison de SELECT INTO OUTFILE/mysqldump et LOAD DATA/mysqlimport . C'était une option très courante si vous aviez besoin de l'accès simultané dans certaines anciennes versions de mysql, car l'utilisation de sql créait de plus grands verrous (ce n'est plus vrai si cela est fait correctement). Comme mysqldump/import ne fonctionne que de manière sérialisée, je vous recommande de rechercher des options pour le paralléliser, très utile pour les grandes tables.

Dans tous les cas, essayez d'éviter plusieurs phrases SQL, car ce sera votre goulot d'étranglement le plus important si vous exécutez de nombreuses requêtes différentes (qui doivent être exécutées, analysées et optimisées individuellement).


* Les structures MyISAM ne peuvent pas être copiées à chaud, mais il est très facile de les synchroniser temporairement sur le disque avec FTWRL.

0
jynus

déplacer des données d'une table à une autre dans le schéma

create table your_table_name select * from old_schema_table;

0
Shahzad Hussain