MySQLテーブルに約4,000万行あり、このテーブルを同じデータベース内の別のテーブルにコピーしたいと思います。これを行う最も効率的な方法は何ですか?どのくらいの時間がかかりますか(およそ)?
mydb.mytb
と作成したいmydb.mytbcopy
このコピーを行うには5つのアプローチがあります
mysql
クライアントで、次を実行します
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}
コピーしたい場合mydb.mytb
を既存のテーブルにmydb.mytbcopy
、および2つのテーブルの構造は同じです。
INSERT INTO mytbcopy SELECT * FROM mytb;
#APPROACH 1のように、#APPROACH 6は、 4,000万行
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サーバーの構成、テーブルの構造、インデックスのレイアウトなどがわからないので、時間を見積もることはできません。
MyISAM *とは異なり、InnoDBテーブルは、データディクショナリ(および、マージバッファーなど、テーブルが依存する他の構造体)の一部がメモリ(サーバーが実行中の場合)および共通/メインテーブルスペース、別名ibdata1
という大きなファイル。
Percona Server> = 5.1またはMySQL> = 5.6を使用している場合は、トランスポータブルテーブルスペースがサポートされているため、ファイルシステムから直接テーブルをエクスポートおよびインポートできます。これは MySQL および Percona のメソッドです。どちらの場合も、innodb_file_per_table
オプションを使用してテーブルを作成し、DISCARD TABLESPACE/IMPORT TABLESPACE
および/またはPercona Xtrabakupを使用する必要があります(エクスポートをオンラインで実行する場合)。 Percona ServerまたはXtrabakupはWindowsでは使用できないことに注意してください。
この方法は、一般的に言えば、ファイルシステムコマンド(cp、rsync)を使用してファイルをコピーするのと同じくらい高速です。
これは、MySQL <5.6(ハックな方法で)のリストアで機能する場合がありますが、テーブルのコピーでは機能しません。そのような場合、それを行う1つの方法は、SQLを使用することです。
CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table SELECT * FROM old_table;
これは、InnoDBがHandler_read_rnd_next
およびHandler_write
を行ごとに1回実行できるのと同じくらい高速になります。この方法を使用する場合は、少なくとも一時的に永続性オプションを無効にし、大きなバッファープールとトランザクションログがあることを確認してください。このような状況では、インポート時間を短縮できる可能性がありますが、完全にメモリに収まるわけではないため、多くの時間を期待してください。また、1つのトランザクションで4000万行をインポートしようとしているため、問題が発生する可能性があります。
この2番目のケースでの実際の推奨事項は、pt-archiverのようなものを使用することです。私が今述べたものと同様ですが、それは「チャンク」で行われ、トランザクションのオーバーヘッドを回避します(速くはないかもしれませんが、失敗した場合、テーブル全体をロールバックしようとはしません。 )。あなたが言及するデータサイズについては、これがおそらく最善の方法です。
最後のオプションは、CSV(またはTSV)形式を使用して、SELECT INTO OUTFILE/mysqldumpおよびLOAD DATA/mysqlimportを組み合わせてエクスポートおよびインポートすることです。 。 sqlを使用するとより大きなロックが作成されるため(これを正しく行うともう当てはまりません)、mysqlの特定の古いバージョンで同時実行性が必要な場合、これは非常に一般的なオプションでした。 mysqldump/importはシリアル化された方法でのみ機能するため、それを並列化するためのオプションを調査することをお勧めします。これは大きなテーブルに非常に役立ちます。
いずれの場合も、複数のSQL文を回避するようにしてください。多数の異なるクエリ(個別に実行、解析、最適化する必要がある)を実行する場合、これが最も重要なボトルネックになるためです。
* MyISAM構造はホットな方法でコピーできませんが、FTWRL
を使用して一時的にディスクに同期することは非常に簡単です。
スキーマ内のあるテーブルから別のテーブルにデータを移動する
create table your_table_name select * from old_schema_table;