MySQLテーブルには約4,000万行があり、このデータベースを同じデータベース内の別のテーブルにコピーしたいと思います。これを行う最も効率的な方法は何ですか?どれくらいの時間がかかりますか(約)?
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
既存のtable にコピーする場合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サーバー、テーブル構造、インデックスレイアウト、およびこれらのようなものの構成がわからないため、時間の見積もりはできません。
InnoDBテーブルは、MyISAM *とは異なり、「ただコピー」することはできません。データディクショナリ(およびテーブルが依存している可能性のある他の構造(マージバッファなど)の一部)はメモリ(サーバーが実行されている場合)および共通/メインテーブルスペース、別名その大きなファイル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つのトランザクションで4,000万行をインポートしようとしているため、問題が発生する可能性があります。
私の実際の推奨は、この2番目のケースで、pt-archiverのようなものを使用することです。これは、先ほど述べた操作と同様の操作を実行しますが、トランザクションオーバーヘッドを回避して「チャンク」で実行されます(より速くなることはありませんが、障害が発生した場合、テーブル全体をロールバックしようとはしません。あなたが言及したデータサイズについては、これがおそらく最善の方法です。
最後のオプションは、CSV(またはTSV)形式を使用して、SELECT INTO OUTFILE / mysqldumpとLOAD DATA / mysqlimportを組み合わせてエクスポートおよびインポートすることです。これは、特定の古いバージョンのmysqlで同時実行が必要な場合に非常に一般的なオプションでした。sqlを使用するとより大きなロックが作成されたためです(正しく行われた場合、これは当てはまりません)。mysqldump / importはシリアル化された方法でのみ機能するため、並列化するオプションを調査することをお勧めします。これは大きなテーブルに非常に役立ちます。
いずれにせよ、複数のSQL文(個別に実行、解析、最適化する必要のある)のさまざまなクエリを実行する場合に最も重要なボトルネックになるため、複数のSQL文を避けるようにしてください。
* MyISAM構造は、ホットな方法でコピーすることはできませんが、一時的にを使用して一時的にディスクに同期することは非常に簡単FTWRL
です。
スキーマ内のあるテーブルから別のテーブルにデータを移動するには
create table your_table_name select * from old_schema_table;