InnoDB挿入の高速化


8

私はモンドリアンOLAPでOLAPを研究している大学院生です。そのため、最初の読み込みでデータをより速くInnoDB(MySQL 5.5)に挿入したいと考えています。この環境では、私しかユーザーがいないので、挿入速度をもっと緩やかに設定できると思います。現在、私は以下のテクニックを使用しています。

  • 無効にする log_bin
  • 可能にする skip-innodb-doublewrite
  • セットtransaction_isolationREAD-COMMITTEDREAD-UNCOMMITTED(実際にREAD-COMMITED
  • セットinnodb_flush_log_at_trx_commit02(実際に0
  • innodb_buffer_pool_size5GBに設定(システムには6GB RAMがあります)

InnoDBに高速に挿入するためのテクニックは他にありますか?そして、私は変更する必要がinnodb_io_read_threadありinnodb_io_write_threadますか?さらに詳しい情報が必要な場合は、教えてください。

回答:


9

提案#1

マシンに複数のコアがある場合は、以下を増やす必要があります。

[mysqld]
innodb_read_io_threads = 64
innodb_write_io_threads = 64
innodb_io_capacity = 5000

これは何?

  • innodb_read_io_threads -InnoDBでの読み取り操作のI / Oスレッドの数。
  • innodb_write_io_threads -InnoDBでの書き込み操作のI / Oスレッドの数。
  • innodb_io_capacity-バッファープールからのページのフラッシュや挿入バッファーからのデータのマージなど、InnoDBバックグラウンドタスクによって実行されるI / Oアクティビティの上限。

提案#2

システムテーブルスペース(ibdata1)からデータとインデックスを分離するには、InnoDBの完全な再構築を実行する必要があります。複雑に聞こえますが、非常に簡単です。これについては、DBA StackExchange(2012年8月29日)StackOverflow(2010年10月29日で書きました。基本的な手順は

  • 走る SET GLOBAL innodb_fast_shutdown = 0;
  • mysqldumpですべてのデータをSQLダンプ
  • service mysql stop
  • 次のファイルを削除します
    • ibdata1
    • ib_logfile0
    • ib_logfile1
  • service mysql start

を実行する前にservice mysql start、次の行を追加しますmy.cnf

innodb_open_files=32768

これにより、個々のテーブルに専用のファイルハンドルができます。デフォルトは300です。ファイルハンドルはキャッシュされることがわかっています。これを非常に高く設定し、すぐに天井にぶつかると、速度が低下します。少数のテーブルで作業している場合、これは当てはまりません。


ご提案ありがとうございます。私は今の提案#2を試してみましょう、と私は調整するだろうinnodb_read_io_threadsinnodb_write_io_threadsと`innodb_io_capacity」。
inohiro

「次のファイルibdata1を削除してください」Sheesh、警告なし。
magallanes

6

InnoDBへのデータの一括読み込み専用のドキュメント全体があります。主なポイント:

  1. 自動コミットを無効にして、各挿入ステートメントの余分なログフラッシュを回避します。 SET autocommit=0;...sql import;COMMIT;
  2. 外部の一意のチェックを無効にします(すべてのインデックスを完全に無効にすることはできません)。

    SET unique_checks=0;
    SET foreign_key_checks=0;
    
  3. innodb_autoinc_lock_modeを1(デフォルト)ではなく2に設定する可能性があります。ここでは、この設定に関するドキュメントです。

3番目の方法は役立つ場合とそうでない場合があります。そのため、このリンクを読んで、最初にデータをロードする方法を確認することをお勧めします。たとえば、ロードを複数の挿入に分割して同時に実行する場合は、値を2に設定することは間違いなく役立ちます。1つの大きな複数行の挿入を実行している場合、(もしあれば)多くは実行されません。助けて。

この最初の挿入のバイナリログを回しているので、自動インクリメント数のギャップを気にする必要はありません(同時挿入を行う場合)。


回答ありがとうございます!一括挿入は非常に高速に見えるので、後で試します。
inohiro

autocommit = 0を設定するだけで、スループットが桁違いに増加しました。ありがとう!
Alex Barker

1

次の方法を使用して、挿入を高速化できます。

  • 同じクライアントから同時に多くの行を挿入する場合はINSERT、複数のVALUESリストを含むステートメントを使用して、一度に複数の行を挿入します。これは、個別の単一行INSERTステートメントを使用するよりもかなり高速(場合によっては何倍も高速)です。空でないテーブルにデータを追加する場合は、bulk_insert_buffer_size変数を調整して、データ挿入をさらに高速にすることができます。
  • テキストファイルからテーブルをロードする場合は、を使用しますLOAD DATA INFILE。これは通常、INSERTステートメントを使用するよりも20倍高速です。見る
  • 列にはデフォルト値があるという事実を利用してください。挿入する値がデフォルトと異なる場合にのみ、値を明示的に挿入します。これにより、MySQLが実行する必要がある解析が減り、挿入速度が向上します。
  • InnoDBテーブルに固有のヒントについては、セクション9.5.5「InnoDBテーブルの一括データロード」を参照してください。

0

プランA:「バッチ」INSERT-INSERTステートメントごとに複数の行。ステートメントごとに約1000行を提案します。autocommit = on、明示的なBEGIN ... COMMITなし

プランB:データの読み込み

一度に挿入する行が多すぎる場合、クラッシュが発生した場合にInnoDBが挿入をロールバックできるようにするには、さらに多くの作業を行う必要があります。このため、セット全体を1つのトランザクションに入れるautocommit = offには同意しません。

行セット全体のLOAD DATAでも同じ問題が発生する可能性がありますが、非常に高速です。

buffer_pool = 6Gのうち5Gが大きすぎる寸前です。スワッピングがあると、パフォーマンスが低下します。

パーティション設定を行うと、速度が低下する可能性があります。

SHOW CREATE TABLE-セカンダリキーは深刻なハンディキャップになる可能性があります。

InnoDBを使用していますか?またはXtraDB?


お返事ありがとうございます。私はInnoDBを使用しています。プランBよりもプランAのほうLOAD DATAが速いように見えますが、データをCSVとして一度にテキストに書き込む必要がありLOAD DATAます。/をbuffer_pool_size4GBに設定します。
inohiro
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.