web-dev-qa-db-ja.com

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

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

15
Devashish Dixit

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}

分析

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

コピーしたい場合mydb.mytbを既存のテーブルに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サーバーの構成、テーブルの構造、インデックスのレイアウトなどがわからないので、時間を見積もることはできません。

試してみる !!!

23
RolandoMySQLDBA

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を使用して一時的にディスクに同期することは非常に簡単です。

0
jynus

スキーマ内のあるテーブルから別のテーブルにデータを移動する

create table your_table_name select * from old_schema_table;

0
Shahzad Hussain