web-dev-qa-db-ja.com

MySQL最適化INSERT速度がインデックスのために遅くなる

MySQL Docs 言う:

Bツリーインデックスを想定すると、テーブルのサイズにより、ログNによるインデックスの挿入が遅くなります。

これは、新しい行を挿入するたびに、挿入速度がlog Nの係数だけ遅くなることを意味しますか。ここで、Nは行数と想定しています。 1つのクエリにすべての行を挿入しても、つまり:

INSERT INTO mytable VALUES (1,1,1), (2,2,2),  (3,3,3), .... ,(n,n,n)

ここで、nは〜70,000です

現在、次の構造を持つテーブルに約147万行あります。

CREATE TABLE mytable (
   `id` INT,
   `value` MEDIUMINT(5),
   `date` DATE,
   PRIMARY_KEY(`id`,`date`)
) ENGINE = InnoDB

上記の方法でトランザクションに挿入すると、コミット時間は約275秒になります。新しいデータは毎日追加されるため、これをどのように最適化できますか?挿入時間は低下し続けます。

また、クエリ以外に役立つ可能性のあるものはありますか?多分いくつかの構成設定?

可能な方法1-インデックスの削除

挿入直前にインデックスを削除すると、挿入速度が向上する可能性があることを読みました。そして挿入後、インデックスを再度追加します。しかし、ここでは唯一のインデックスが主キーであり、それをドロップしても私の意見ではあまり役に立ちません。また、主キーがdroppedである間は、すべての選択クエリの動作が遅くなります。

他に可能な方法は知りません。

Edit:以下は、〜1.47 milの行を持つテーブルに〜60,000行を挿入するいくつかのテストです:

上記のプレーンクエリを使用:146秒

MySQLのLOAD DATA infileを使用:145秒

MySQLのLOAD DATA infileを使用し、David Jashiの回答で示唆されているようにcsvファイルを分割します60行で136秒、各行に1000行、136秒それぞれ10,000行の6つのファイル

主キーの削除と再追加:キーの削除に11秒、データの挿入に0.8秒かかりましたが、主キーの再追加に153秒、完全にかかっていました〜 165秒

13

高速挿入が必要な場合、最初に必要なのは適切なハードウェアです。これは、十分な量のRAM、機械式ドライブの代わりにSSD、そしてかなり強力なCPUを想定しています。

InnoDBを使用するので、デフォルトの構成は低速で古いマシン用に設計されているため、最適化する必要があります。

InnoDBの構成に関する優れた資料を次に示します

その後、1つ知っておく必要があります。これが、データベースが内部でどのように機能するか、ハードドライブがどのように機能するかなどです。次の説明でメカニズムを簡略化します。

トランザクションはMySQLで、ハードドライブがデータを書き込んだことを確認するのを待っています。そのため、機械式ドライブではトランザクションが遅く、1秒あたり200〜400回の入出力操作を実行できます。つまり、機械式ドライブでInnoDBを使用すると、毎秒200件の挿入クエリを取得できます。当然、これは単純化された説明です、何が起こっているのかを概説するために、トランザクションの背後にある完全なメカニズムではありません

クエリ、特にテーブルのサイズに対応するクエリはバイト数が比較的小さいため、1つのクエリで貴重なIOPSを効率的に浪費しています。

1つのトランザクションで複数のクエリ(100または200以上、正確な数はありません。テストする必要があります)をラップしてからコミットすると、即座に1秒あたりの書き込み数が増えます。

Perconaの人たちは、比較的安価なハードウェアで1秒あたり15,000回の挿入を達成しています。 5kの挿入でも1秒は悪くありません。あなたのようなテーブルは小さく、私は同様のテーブル(さらに3列)でテストを行い、240GB SSDを搭載した16GB RAMマシン(1ドライブ、RAIDなし、テスト目的で使用されます)。

TL; DR:-上記のリンクに従い、サーバーを構成し、SSDを取得し、1つのトランザクションで複数の挿入をラップして利益を上げます。また、インデックス作成をオフにしてからオンにしないでください。いつかは処理に費やし、IO作成に時間を費やすためです。

20
N.B.

インデックスの削除はとにかく確かに役立ちます。 LOAD DATAの使用も検討してください。いくつかの比較とベンチマークを見つけることができます ここ

また、PRIMARY KEYを作成するときは、テーブルの最初に来るフィールドを順番に使用します。つまり、構造の2番目と3番目のフィールドの場所を入れ替えます。

5
David Jashi

100万行の一括挿入を実行している場合は、インデックスの削除、挿入、およびインデックスの再構築がおそらく高速になります。ただし、問題が単一行の挿入に時間がかかりすぎる場合は、他の問題(メモリ不足など)があり、インデックスを削除してもあまり効果がありません。

3
Old Pro

インデックスの構築/再構築は、高速化しようとしているものです。このテーブル/キー構造が必要な場合は、ハードウェアを高速化するか、サーバーの構成を調整してインデックスの構築を高速化するのがおそらく答えです。サーバーと設定がメモリ内で実行できるようになっていることを確認してください。

それ以外の場合は、挿入速度を向上させる構造とのトレードオフを検討してください。または、3分の挿入で幸せに暮らせる方法を考えてください。

1
JR Lawhorne

場合によっては、トランザクションを中程度のチャンクで挿入すると、いくつかの一括操作が許可されるように見えるため、役立つことがあります。他のケースでは、おそらくロックとトランザクションのオーバーヘッドのために、物事が遅くなっています。

0
jgmjgm