1つのMySQLテーブルから同じデータベースの別のMySQLテーブルにコピーする


14

MySQLテーブルには約4,000万行があり、このデータベースを同じデータベース内の別のテーブルにコピーしたいと思います。これを行う最も効率的な方法は何ですか?どれくらいの時間がかかりますか(約)?


あなたのテーブルのエンジンは何ですか?
アブドゥルマナフ14

InnoDBのエンジン...
Devashishディキシット

回答:


22

あなたが持っている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は、ステップの点では最も簡単ですが、1つのトランザクションに4000万行をプッシュする必要があります。これは、InnoDBストレージエンジンに最も負担がかかります。
  • 他のアプローチの場合、mysqldumpは数千行のチャックで4000万行を送信します
    • APPROACH#2およびAPPROACH#3は、テストデータベースにテーブルをmysqldumpします。テストデータベースにテーブルを作成した後、テーブルの名前が変更され、元のデータベースに移動されます
    • APPROACH#4およびAPPROACH#5は、mysqldumpからのストリームに対してsedを使用してテーブルの名前を変更し、INSERTコマンドをエコーし​​ます。
    • APPROACH#2およびAPPROACH#4は出力ファイルの代わりにパイプを使用します
    • アプローチ#3およびアプローチ#5は、後続のリロードにoutpuitファイルを使用します

mydb.mytb既存のtable にコピーする場合mydb.mytbcopy、2つのテーブルの構造は同じです:

アプローチ#6

INSERT INTO mytbcopy SELECT * FROM mytb;

#APPROACH 1と同様に、#APPROACH 6には4,000万行の単一のトランザクションがあります

アプローチ#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サーバー、テーブル構造、インデックスレイアウト、およびこれらのようなものの構成がわからないため、時間の見積もりはできません。

試してみる !!!


0

InnoDBテーブルは、MyISAM *とは異なり、「ただコピー」することはできません。データディクショナリ(およびテーブルが依存している可能性のある他の構造(マージバッファなど)の一部)はメモリ(サーバーが実行されている場合)および共通/メインテーブルスペース、別名その大きなファイルibdata1

Percona Server> = 5.1またはMySQL> = 5.6を使用している場合、トランスポータブルテーブルスペースのサポートがあり、ファイルシステムからテーブルを直接エクスポートおよびインポートできます。これは、MySQLPerconaのメソッドです。どちらの場合でも、innodb_file_per_tableオプションを使用してテーブルを作成し、DISCARD TABLESPACE/IMPORT TABLESPACEPercona 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_nextHandler_write、行ごとに一度。この方法を使用する場合は、少なくとも一時的に永続性オプションを無効にし、大きなバッファプールとトランザクションログがあることを確認してください。このような状況では、インポート時間は短縮される可能性がありますが、メモリに完全には収まらないため、多くの時間を期待してください。また、1つのトランザクションで4,000万行をインポートしようとしているため、問題が発生する可能性があります。

私の実際の推奨は、この2番目のケースで、pt-archiverのようなものを使用することです。これは、先ほど述べた操作と同様の操作を実行しますが、トランザクションオーバーヘッドを回避して「チャンク」で実行されます(より速くなることはありませんが、障害が発生した場合、テーブル全体をロールバックしようとはしません。あなたが言及したデータサイズについては、これがおそらく最善の方法です。

最後のオプションは、CSV(またはTSV)形式を使用して、SELECT INTO OUTFILE / mysqldumpとLOAD DATA / mysqlimportを組み合わせてエクスポートおよびインポートすることです。これは、特定の古いバージョンのmysqlで同時実行が必要な場合に非常に一般的なオプションでした。sqlを使用するとより大きなロックが作成されたためです(正しく行われた場合、これは当てはまりません)。mysqldump / importはシリアル化された方法でのみ機能するため、並列化するオプションを調査することをお勧めします。これは大きなテーブルに非常に役立ちます。

いずれにせよ、複数のSQL文(個別に実行、解析、最適化する必要のある)のさまざまなクエリを実行する場合に最も重要なボトルネックになるため、複数のSQL文を避けるようにしてください。


* MyISAM構造は、ホットな方法でコピーすることはできませんが、一時的にを使用して一時的にディスクに同期することは非常に簡単FTWRLです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.