「LOAD DATA INFILE」が通常のINSERTステートメントよりも高速なのはなぜですか?


22

私は、csvファイルから読み取り、データベースにデータを挿入するステートメントを使用して、1秒あたり60,000の挿入を達成できると述べた記事をLOAD DATA IN FILE読みました。

なぜ通常の挿入と異なるのですか?

編集:
私はただ1つのINSERTステートメントを呼び出すことでラウンドトリップを減らしました:

INSERT INTO tblname
VALUES (NULL,2,'some text here0'),(NULL,2,'some text here1')
    ,(NULL,2,'some text here2'),(NULL,2,'some text here3')
    .....,(NULL,2,'some text here3000');

これはどうですか?


私は対拡張挿入をベンチマーキング、媒体上の記事を書いたLOAD DATA INFILEMySQLでの高速挿入。結論:LOAD DATA INFILE拡張挿入を使用した場合のパフォーマンスの65%を達成できます 。最新のハードウェアでは、毎秒240,000の挿入を受け取りました。
ベンジャミン

回答:


26

LOAD DATA INFILEと拡張INSERTにはそれぞれ明確な利点があります。

LOAD DATA INFILEは、次のような機能を実行するために、1回の操作で表データを大量にロードするために設計されています。

  • 最初の行をスキップする
  • 特定の列をスキップする
  • 特定の列の変換
  • 特定の列のロード
  • 重複キーの問題の処理

解析に必要なオーバーヘッドが少ない

一方、1,000,000行ではなく100行のみをインポートする場合は、拡張INSERTが賢明です。

mysqldumpは、INSERTごとに数百または数千の行の挿入を実行する際に、テーブル設計とデータを運ぶために、拡張INSERTを中心に設計されていることに注意してください。LOAD DATA INFILEは、常にスキーマとデータの間に物理的な二分法を作成します。

アプリケーションの観点から見ると、LOAD DATA INFILEは、拡張INSERTよりもスキーマの変更に敏感ではありません。

LOAD DATA INFILEを使用することの良い点、悪い点、onい点を行き来できます。使用する手法に関係なく、常にbulk_insert_buffer_sizeを設定する必要があります。どうして?

bulk_insert_buffer_sizeのMySQLドキュメントによると:

MyISAMは、特別なツリーのようなキャッシュを使用して、空でないデータを追加するときに、INSERT ... SELECT、INSERT ... VALUES(...)、(...)、...、およびLOAD DATA INFILEの一括挿入を高速化しますテーブル。この変数は、スレッドごとのキャッシュツリーのサイズをバイト単位で制限します。0に設定すると、この最適化が無効になります。デフォルト値は8MBです。

何年もの間、私はクライアントがこれを設定せずに8MBのままにしておくのを見てきました。次に、LOAD DATA INFILEを使用するか、mysqldumpsをインポートすることを決定すると、何か間違っていると感じることがあります。通常、これを中程度の256Mに設定することをお勧めします。場合によっては、512M。

十分な大きさのバルクINSERTバッファーを作成したら、どちらの手法を使用してもアカデミックになり、最終的には個人的な選択になります。必要に応じて100行だけを一括挿入するアプリケーションでは、拡張INSERTを使用してください。

公平に言うと、主に構成が考慮されていないため、LOAD DATA INFILEは通常のINSERTステートメントがロードされたステートメントの一種であるよりも高速であると言っています。LOAD DATA INFILEと適切なbulk_insert_buffer_sizeを使用した拡張INSERTの間にベンチマークを設定した場合でも、各行の解析で節約されるナノ秒は、LOAD DATA INFILEを優先して名目上の結果しか得られません。

さあ、これをmy.cnfに追加してください

[mysqld]
bulk_inset_buffer_size=256M

拡張INSERTを起動する前に、セッションのみに設定することもできます

SET bulk_insert_buffer_size= 1024 * 1024 * 256;

更新2012-07-19 14:58 EDT

物事を把握するために、バルク挿入バッファーは、InnoDBではなくMyISAMテーブルのロードにのみ役立ちます。私はInnoDBのバルクロードに関する最新の投稿を書きました:infileからのMysqlのロードがハードドライブで待機しています


4

ほとんどのデータベース管理システムには、大量のデータをすばやくロードするためのバルクロード機能があります。INSERT文では、文単位の荷物を大量に持っている-ロック、トランザクション境界、参照整合性をチェックし、リソースの割り当て、I / Oあたりの文基づいて行わなければならないこと。

一括挿入操作はプロセスを合理化するため、このようなものは行ごとのオーバーヘッドがはるかに少なくなります。DBMSは、insertステートメントを使用するよりもはるかに高速に大量のデータを一括ロードできます。


3

個々のINSERTステートメントの解析と実行は、CSVファイルを列に分割して直接ロードするよりもはるかに大きなオーバーヘッドを伴います。

INSERTステートメントは、MySQLエンジンによって個別に解析され、有効性をチェックする必要があります-これは余分なCPUリソースを消費し、さらにクライアント<>サーバーの往復が必要です。これは、を介してバルクロードするときに発生する必要はありませんLOAD DATA INFILELOAD DATA INFILE空のテーブルにロードするために使用するときに実行できる最適化もあります。詳細については、このリンクを参照してください。


私の質問の編集部分を参照してください。
ALH

準備済みステートメントを使用する場合、解析のオーバーヘッドはありません。
ベンジャミン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.