web-dev-qa-db-ja.com

MySQL LOAD DATA INFILEは、InnoDBエンジンで数ギグ入力した後、80%遅くなります

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....

それがうまく始まって、時間が経つにつれて遅くなっている理由がわかりません。

また、同じ設定を使用して、同じLOAD DATA INFILEコマンドをInnoDBとMyISAMを使用するテーブルと5GBのテストデータセットで実行しました。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を超えるテーブルへの大量のデータのロードをサポートしていないようです。

14
David Parks

観測#1

autocommitをオフにしているようです。これにより、ibdata1に大量のデータが蓄積されます。どうして?

Ibdata1に保存される情報には7つのクラスがあります。

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

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

推奨:自動コミットをオンのままにします

観測#2

私はあなたがこれを持っているのを見る:

alter table item_load disable keys;

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

  • MyISAM:DISABLE KEYSは、単にMyISAMテーブルのセカンダリインデックスの更新を停止します。キーを無効にした状態でMyISAMテーブルにINSERTを一括で実行すると、主キーとすべての一意のインデックスの構築とともにテーブルの読み込みが高速になります。 ENABLE KEYSを実行すると、すべてのセカンダリインデックスがテーブル上で線形に構築され、.MYDに追加されます。
  • InnoDB:InnoDBの内部図に示されているように、システムテーブルスペース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テーブルでも実行できますが、 ACID準拠の動作 および [〜 #〜] mvcc [〜#〜] InnoDBは依然としてパフォーマンスのボトルネックになる可能性があります。特に、VARCHARフィールドが大幅に増加する場合は、ibdata1に書き込まれます。

7
RolandoMySQLDBA

この質問に対する最後の答えは、大規模な参照テーブルにInnoDBを使用しないことでした。 MyISAMは高速で、負荷全体のディスク速度のほぼ完全なスループットに達しており、InnoDBは停滞しています。 MyISAMは単純ですが、この場合、このテーブルの要件もそうです。 LOAD DATA INFILEを介したバルクロードを含む単純な参照テーブルの場合、MyISAMが適しています。

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

6
David Parks

入力ファイルを小さなチャンクに分割してみることができます。

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

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

さらに詳しいアイデアについては、こちらをご覧ください: http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql

5
bnadland

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の使用

2
KKYadav