从一个MySQL表复制到同一数据库的另一个MySQL表


Answers:


23

假设您有mydb.mytb并且想要创建mydb.mytbcopy

我有五(5)种方法来制作此副本

方法1

mysql客户端中,运行以下命令

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

方法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"

方法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"

方法#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

方法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}

分析

  • 就步骤而言,方法1最简单,但需要将4000万行推入一个事务中。这将对InnoDB存储引擎造成最大的负担。
  • 对于其他方法,mysqldump将以成千上万的行发送4000万行
    • 方法2方法3会将表mysqldump到测试数据库中。在测试数据库中创建表后,随后将其重命名并移入原始数据库
    • APPROACH#4APPROACH#5对mysqldump的流使用sed重命名表,因为它回显了INSERT命令
    • 方法2方法4使用管道代替输出文件
    • 方法3方法5使用Outpuit文件进行后续重新加载

如果要复制mydb.mytb到已经存在的表中mydb.mytbcopy,并且两个表具有相同的结构:

方法#6

INSERT INTO mytbcopy SELECT * FROM mytb;

#APPROACH 1一样,#APPROACH 6将具有4000万行的单笔交易

方法#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

这种方法不会删除表。它只是生成INSERT

结语

由于我不知道DB Server的组成,表结构,索引布局以及诸如此类的内容,因此我无法给您时间估计。

试试看 !!!


0

与MyISAM *不同,InnoDB表不能“被复制掉”,因为它的数据字典(以及表所依赖的其他结构,如合并缓冲区)的一部分位于内存(如果服务器正在运行)中,并且位于公用/主表空间,也就是那个大文件ibdata1

如果您使用的是Percona Server> = 5.1或MySQL> = 5.6,则支持可移动表空间,这使您可以直接从文件系统导出和导入表。这是MySQLPercona的方法。在这两种情况下,都要求您使用innodb_file_per_table选项创建了表,并且涉及到DISCARD TABLESPACE/IMPORT TABLESPACE和/或Percona Xtrabakup的用法(如果要在线导出)。请注意,Percona Server或Xtrabakup不适用于Windows。

一般来说,此方法将与使用文件系统命令(cp,rsync)复制文件一样快

尽管在某些情况下,这可以在MySQL <5.6(以一种怪异的方式)进行还原的MySQL中工作,但不适用于表副本。在这种情况下,一种方法是使用SQL

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

这将与InnoDB可以执行的速度一样快, Handler_read_rnd_next并且Handler_write每行一次。如果使用此方法,请确保至少暂时禁用持久性选项,并且您具有较大的缓冲池和事务日志。在这种情况下,它可以减少导入时间,但是肯定不能完全放入内存中,因此需要很多时间。另外,您尝试在单个事务中导入40M行,这可能会导致问题。

在第二种情况下,我的实际建议是使用类似pt-archiver之类的东西,因为它会执行与我刚才提到的操作类似的操作,但是将以“块”方式完成,避免了事务性开销(它可能会不会更快,但是在失败的情况下,它不会尝试回滚整个表,要花很多时间)。对于您提到的数据大小,这可能是最好的方法。

最后一个选择是使用CSV(或TSV)格式进行导出和导入,并结合使用SELECT INTO OUTFILE / mysqldump和LOAD DATA / mysqlimport。如果您需要在某些旧版本的mysql中进行并发操作,这是一个非常常见的选择,因为使用sql会创建更大的锁(如果正确完成,将不再适用)。由于mysqldump / import仅以序列化方式工作,因此我建议您研究将其并行化的选项,这对于大型表非常有用。

无论如何,都应避免使用多个SQL语句,因为如果您执行许多不同的查询(必须分别执行,解析和优化),这将是您最重要的瓶颈。


*不能以热方式复制MyISAM结构,但是使用临时将它们临时同步到磁盘非常容易FTWRL


0

在架构中将数据从一个表移动到另一个表

create table your_table_name select * from old_schema_table;

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.