web-dev-qa-db-ja.com

InnoDBは600MBファイル、MyISAMを数分でインポートするのに1時間以上かかります

現在、アプリのパフォーマンスをテストする環境の作成に取り組んでいます。私はMySQLとInnoDBでテストして、どれが私たちに最も役立つかを調べています。この環境内で、データベースを自動的に準備し(既存のダンプをロード)、テストツールをインストルメントします。

MySQLとInnoDBで同じデータダンプをテストする準備をしていますが、InnoDB部分で使用可能な速度で初期インポートを実行できません。最初のダンプには時間がかかりましたが、それはまだ気になりませんでした。

$ for i in testdb_myisam testdb_innodb; do time mysqldump --extended-insert $i > $i.sql; done

real    0m38.152s
user    0m8.381s
sys     0m2.612s

real    1m16.665s
user    0m6.600s
sys     0m2.552s

ただし、インポート時間はまったく異なりました。

$ for i in  testdb_myisam testdb_innodb; do time mysql $i < $i.sql; done

real    2m52.821s
user    0m10.505s
sys     0m1.252s

real    87m36.586s
user    0m10.637s
sys     0m1.208s

調査の後、私はやって来ました MyISAMからInnoDBにテーブルを変更するとシステムが遅くなります そして使用set global innodb_flush_log_at_trx_commit=2

$ time mysql testdb_innodb < testdb_innodb.sql

real    64m8.348s
user    0m10.533s
sys     0m1.152s

私見はまだ衝撃的に遅い。私も無効にしたlog_binこれらのテストの場合、ここに すべてのmysql変数 のリストがあります。

この長いInnoDB時間を受け入れる必要がありますか、それとも改善できますか?このMySQLサーバーはこのテスト環境専用であるため、完全に制御できます。

最初のインポートにのみ特別な構成を適用し、アプリケーションテスト用に変更して元の環境に一致させることができます。

更新:

フィードバックを受けて、自動コミットとさまざまなチェックを無効にしました。

$ time ( echo "SET autocommit=0; SET unique_checks=0; SET foreign_key_checks=0;" \
; cat testdb_innodb.sql ; echo "COMMIT;" ) | mysql testdb_innodb;date

real    47m59.019s
user    0m10.665s
sys     0m2.896s

速度は向上しましたが、それほどではありません。テストに欠陥はありますか?

更新2:

インポートには約8分しかかからず、別のマシンにアクセスすることができました。構成を比較し、MySQLインストールに次の設定を適用しました。

innodb_additional_mem_pool_size = 20971520
innodb_buffer_pool_size = 536870912
innodb_file_per_table
innodb_log_buffer_size = 8388608
join_buffer_size = 67104768
max_allowed_packet = 5241856
max_binlog_size = 1073741824
max_heap_table_size = 41943040
query_cache_limit = 10485760
query_cache_size = 157286400
read_buffer_size = 20967424
sort_buffer_size = 67108856
table_cache = 256
thread_cache_size = 128
thread_stack = 327680
tmp_table_size = 41943040

これらの設定により、約25分になりました。 MyISAMにかかる数分からはまだ遠いですが、私にとっては使いやすくなっています。

58
mark

InnoDBパフォーマンスチューニングのヒント からのバルクデータ読み込みのヒント最初の1つ):

  • データをInnoDBにインポートするときは、挿入ごとにディスクへのログフラッシュが必要になるため、MySQLで自動コミットモードが有効になっていないことを確認してください。インポート操作中に自動コミットを無効にするには、SET autocommitおよびCOMMITステートメントで囲みます。

    SET autocommit=0;
    ... SQL import statements ...
    COMMIT;
    

    Mysqldumpオプション--optを使用すると、SET autocommitおよびInnoDBステートメントでラップしなくても、COMMITテーブルに高速でインポートできるダンプファイルを取得できます。

  • セカンダリキーにUNIQUE制約がある場合、インポートセッション中に一意性チェックを一時的にオフにすることで、テーブルのインポートを高速化できます。

    SET unique_checks=0;
    ... SQL import statements ...
    SET unique_checks=1;
    

    大きなテーブルの場合、InnoDBは挿入バッファーを使用してバッチでセカンダリインデックスレコードを書き込むことができるため、これにより多くのディスクI/Oが節約されます。データに重複キーが含まれていないことを確認してください。

  • テーブルにFOREIGN KEY制約がある場合、インポートセッション中に外部キーチェックをオフにすることで、テーブルのインポートを高速化できます。

    SET foreign_key_checks=0;
    ... SQL import statements ...
    SET foreign_key_checks=1;
    

    大きなテーブルの場合、これにより多くのディスクI/Oを節約できます。

IMO、章全体を読む価値があります。

129
Pascal Thivent

最初にトランザクションを開始し、最後にコミットしようとしましたか? リンクした質問」から、「データの挿入」ステップを変更して、トランザクションを開始時に開始し、終了時にコミットします。改善が得られます。それを保証します。」

InnoDBはトランザクション対応であり、MyISAMはトランザクション対応ではないことに注意してください。トランザクションを明示的に制御しない場合、トランザクションエンジンはすべてのステートメントを個別のトランザクションとして扱います。これには費用がかかります。

5
T.J. Crowder

ハードドライブがボトルネックであることがわかりました。昔ながらのディスクは絶望的で、SSDは大丈夫ですが、まだ完璧にはほど遠い状態です。 tmpfsへのインポートとデータのコピーははるかに高速です。詳細: https://dba.stackexchange.com/a/89367/56667

2
egmont

大量のインポートを実行する際に問題が発生したため、受け入れられた回答をお勧めします。また、次の方法で物事を大幅にスピードアップできることがわかりました。

  1. 主キー以外のすべてのインデックスを削除し、データをロードしてからインデックスを再追加します
  2. innodb_log_file_size * innodb_log_files_in_groupは、1秒未満の頻度でディスクへの書き込みを回避するのに十分です。

#2に関しては、最新のシステムではデフォルトの5M * 2では十分ではありません。詳細については、 innodb_log_file_size および innodb_log_files_in_group

1
KCD