web-dev-qa-db-ja.com

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

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

通常のインサートとなぜ違うのですか?

編集:
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');

これはどうですか?

22
ALH

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を使用することの良い点、悪い点、醜い点を行き来することができます。どの手法を使用する場合でも、常に bulk_insert_buffer_size を設定する必要があります。どうして?

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

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

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

十分な大きさのバルクINSERTバッファーを取得したら、どちらの手法を使用しても、学術的であり、個人的な選択に要約されます。オンデマンドで100行だけを一括でINSERTするアプリケーションでは、拡張INSERTを使用します。

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

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

[mysqld]
bulk_inset_buffer_size=256M

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

SET bulk_insert_buffer_size= 1024 * 1024 * 256;

UPDATE 2012-07-19 14:58 EDT

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

26
RolandoMySQLDBA

ほとんどのデータベース管理システムには、大量のデータをすばやくロードするためのバルクロード機能があります。 INSERTステートメントには、ステートメントごとにかなりの量の手荷物(ロック、トランザクション境界、参照整合性チェック、リソースの割り当て、ステートメントごとに実行する必要があるI/O)があります。

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

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

INSERTステートメントは、MySQLエンジンによって個別に解析され、妥当性がチェックされる必要があります。これにより、余分なCPUリソースが消費され、さらにクライアント<>サーバーのラウンドトリップが必要になります。 LOAD DATA INFILEを介した一括読み込みの場合、これは必要ありません。 LOAD DATA INFILEを使用して空のテーブルにロードするときに実行できる最適化もあります。詳細は this link を参照してください。

3
Philᵀᴹ