MySQLのLOAD DATA INFILEは、InnoDBエンジンでの入力のいくつかのギグの後、80%遅くなります


14

LOAD DATA INFILEを介して100GBのファイルをロードしています。私はMyISAMで数時間成功しました。

私は今InnoDBを使って試しています。ロードは10MB /秒以上で高速に開始されます(テーブルファイルの増大を監視し、file_per_tableオンになっています)。

しかし、約5 GBのデータの後、2〜4 MB /秒の範囲に低下します。20GBを超えると、約2 MB /秒になりました。

InnoDBバッファープールのサイズは8Gです。そして、LOAD DATA INFILEコマンドを実行する前に次のことを行いました。

SET @@session.sql_log_bin=0;
SET autocommit=0;
SET unique_checks=0;
SET foreign_key_checks=0;
alter table item_load disable keys;
//Run LOAD DATA INFILE....

開始が順調に進み、時間がたつにつれて速度が低下している理由がわかりません。

また、同じ設定を使用して、InnoDBとMyISAMおよび5GBテストデータセットを使用したテーブルで同じLOAD DATA INFILEコマンドを実行すると、MyISAMは20倍高速になりました。

InnoDB:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (21 min 25.38 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

MyISAM:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (1 min 2.52 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

他に試してみるべきことはありますか?MyISAMエンジンは、負荷率をはるかに向上させることができます。


追加の詳細:

  • ファイルを個別にロードしようとしましたが、違いはありません。

  • ちなみに、各500MBの150個のファイルがあり、各ファイル内でキーがソートされています。

  • 12時間後に40GBを一晩で取得した後、負荷率は0.5MB /秒に低下しました。つまり、実際には、操作は不可能です。

  • 私は他のフォーラムで同様の質問に対する他の回答を見つけていません。InnoDBは、サイズが数GBを超えるテーブルへの大量のデータのロードをサポートしていないようです。

回答:


7

観察#1

あなたがオフになったのに気づいたautocommit。これにより、ibdata1に大量のデータが蓄積されます。どうして?

ibdata1に保存される情報のクラスは7つ(7)です。

  • InnoDBテーブルのデータページ
  • InnoDBテーブルのインデックスページ
  • データ辞書
  • ダブルライトバッファ
    • データ破損を防止するセーフティネット
    • キャッシュのOSのバイパスを支援
  • バッファーの挿入(セカンダリインデックスへの変更を合理化)
  • ロールバックセグメント
  • ログを元に戻す
  • ここをクリックして、画像表示をご覧ください ibdata1

この情報の一部は、分離レベルに応じて特定のトランザクションに表示されます。このようなアクションは、意図しない主キーロック大量のファントムデータを生成する可能性があります。これらの2つのことが増加すると、かなりの速度低下が予想されます。

勧告:自動コミットをオンのままにしてください

観察#2

あなたはこれを持っていることがわかります:

alter table item_load disable keys;

DISABLE KEYSはInnoDBでは機能しません。その理由は次のとおりです。

  • MyISAM:DISABLE KEYSMyISAMテーブルのセカンダリインデックスの更新を単に停止します。キーを無効にしたMyISAMテーブルに一括挿入すると、PRIMARY KEYとすべての一意のインデックスの構築とともに、テーブルの読み込みが高速になります。実行するとENABLE KEYS、すべてのセカンダリインデックスがテーブル上に直線的に構築され、.MYD
  • InnoDB:InnoDBの内部図に示されているように、システムtablespaveにibdata1は、セカンダリインデックス挿入専用の構造があります。現時点では、MyISAMと同じインデックスを処理する規定はありません。

これを説明するために、MySQLのInnoDBテーブルでDISABLE KEYSを実行しようとする試みに注意してください

mysql> show create table webform\G
*************************** 1. row ***************************
       Table: webform
Create Table: CREATE TABLE `webform` (
  `nid` int(10) unsigned NOT NULL,
  `confirmation` text NOT NULL,
  `confirmation_format` tinyint(4) NOT NULL DEFAULT '0',
  `redirect_url` varchar(255) DEFAULT '<confirmation>',
  `status` tinyint(4) NOT NULL DEFAULT '1',
  `block` tinyint(4) NOT NULL DEFAULT '0',
  `teaser` tinyint(4) NOT NULL DEFAULT '0',
  `allow_draft` tinyint(4) NOT NULL DEFAULT '0',
  `submit_notice` tinyint(4) NOT NULL DEFAULT '1',
  `submit_text` varchar(255) DEFAULT NULL,
  `submit_limit` tinyint(4) NOT NULL DEFAULT '-1',
  `submit_interval` int(11) NOT NULL DEFAULT '-1',
  PRIMARY KEY (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> alter table webform disable keys;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+-------------------------------------------------------------+
| Level | Code | Message                                                     |
+-------+------+-------------------------------------------------------------+
| Note  | 1031 | Table storage engine for 'webform' doesn't have this option |
+-------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select version();
+------------+
| version()  |
+------------+
| 5.5.27-log |
+------------+
1 row in set (0.00 sec)

mysql>

観察#3

MyISAMがInnoDBよりも20倍高速にロードすることに気付きました。24〜25倍速くしたいですか?次に、次を実行します。

ALTER TABLE item_load ROW_FORMAT=Fixed;

これにより、他のDDL変更なしでINSERTの時間を20〜25%短縮できます。副作用:MyISAMテーブルはサイズが80%〜100%大きくなる可能性があり、場合によっては大きくなります。

これをInnoDBテーブルでも実行できますが、特にVARCHARフィールドが大幅に増加する場合は、ACID準拠の動作とInnoDBのMVCCがパフォーマンスのボトルネックになりibdata1ます。


最初の2つの観測は、最初に気づいた後、問題を修正するために追加しようとしたものでした。最初の試みは、innodbをそのままにしておくことでした(ビンロギングをオフにするだけです)。3番目の観測では、データサイズの長さが非常に可変であり、これが問題になると思いますか?このテーブルmyisamを保持する必要があるように感じています。
デビッドパークス

6

この質問に対する最後の答えは、大規模な参照テーブルにInnoDBを使用しないことでした。MyISAMは高速で、ロード全体のディスク速度のほぼ完全なスループットを叫んでいます。InnoDBは動きません。MyISAMは単純ですが、この場合、この表の要件も同様です。LOAD DATA INFILEを介したバルクロードを使用した単純な参照テーブルの場合、MyISAMが最善の方法です。

ただし、MyISAMテーブルとInnoDBテーブルの両方を実行する場合、2つのキャッシュメカニズムのメモリ割り当てを考慮する必要があり、各エンジンには独自のキャッシュがあり、個別のメモリ割り当てが必要です。


5

入力ファイルを小さなチャンクに分割してみてください。

これには個人的にhttp://www.percona.com/doc/percona-toolkit/2.1/pt-fifo-split.html を使用します

インポート中にテーブルのテーブルロックを取得するとどうなりますか?InnoDBの行レベルのロックが遅くなる可能性があります(MyISAMはテーブルロックを使用します)。

また、ここでさらにアイデアを読むことができます:http : //derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql


私のファイルは既に500MBのチャンクになっています。すべてのファイルを単一の名前付きパイプでパイピングして、ロードを容易にしましたが、このアプローチを試してみましょう。
デビッドパークス

ここで違いは見られませんが、DBファイルの11MB /秒の拡張から6MB(約2GB後)のデータへの速度の低下が非常に早く見られ、低下し続けています。私はforループ内のすべてのファイルを個別のmysql呼び出しでロードしています。
デビッドパークス

54sでロードされた最初のファイル、3m39sで2番目、3m9sで3番目、4m7s、5m21sなど。すべてのファイルは同じサイズです。
デビッドパークス

2

PKがAUTO_INCREMENTではない場合、またはcsvファイル内のデータがPKでソートされていない場合、データロードのパフォーマンスに影響している可能性があります。MySQLのテーブルはインデックスであるため、すべてのデータはソート順に格納されます。PK値がAUTO_INCREMENTにない場合、MySQLはデータをソート順に格納するために大量のデータシフトを行う必要があります。これが、テーブルサイズが大きくなり始めたときにデータの読み込みが遅くなる理由です。

LOAD DATA INFILEを使用してAUTO_INCREMENTのPKで91GBのcsvファイルをロードしていますが、スループットの低下は見られません。1秒あたり140K〜145Kの挿入を取得しています。Percona MySQL 5.6.38の使用

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.