web-dev-qa-db-ja.com

mysqlで非常に大きなデータを処理する

長い投稿でごめんなさい!

〜30個のテーブル(InnoDBエンジン)を含むデータベースがあります。これらのテーブルのうち、「トランザクション」と「シフト」の2つだけが非常に大きくなります(最初のテーブルには150万行、シフトには23k行あります)。これですべてが正常に動作し、現在のデータベースサイズに問題はありません。

ただし、同様のデータベース(同じデータ型、設計など)がありますが、はるかに大きくなります。たとえば、「トランザクション」テーブルには約10億レコードがあります(1日あたり約230万トランザクション)そして、MySQLでこのような量のデータをどのように扱うべきかを考えていますか? (読み取りと書き込みの両方が集中します)。 Mysql(より具体的にはInnoDBエンジン)が何十億ものレコードでうまく機能するかどうかを確認するために、関連する多くの投稿を読みましたが、まだいくつか質問があります。私が読んだ関連記事のいくつかは、次のとおりです。

非常に大きなテーブルのパフォーマンスを改善するためにこれまでに理解したこと:

  1. (私の場合はinnoDBテーブルの場合)innodb_buffer_pool_sizeを増やします(たとえば、RAMの最大80%)。また、他のMySQLパフォーマンス調整設定もいくつか見つけました ここperconaブログ
  2. テーブルに適切なインデックスを持っている(クエリでEXPLANを使用)
  3. テーブルを分割する
  4. MySQLシャーディングまたはクラスタリング

ここに私の質問/混乱があります:

  • パーティションについては、使用すべきかどうか疑問があります。一方、多くの人は、テーブルが非常に大きい場合にパフォーマンスを改善することを提案しました。一方で、クエリのパフォーマンスが向上せず、クエリの実行速度が向上しないと言う記事を多く読んでいます(例: here および here )。また、私は MySQLリファレンスマニュアル を読みましたInnoDB外部キーとMySQLパーティショニングは互換性がありません(外部キーがあります)。

  • インデックスに関しては、今のところうまく機能していますが、私が理解している限りでは、非常に大きなテーブルのインデックス作成はより制限的です(Kevin Bedellが彼の答えで述べたように here )。また、インデックスは読み取りを高速化し、書き込みを遅くします(挿入/更新)。したがって、このような大規模なDBを持つ新しい類似プロジェクトの場合、まずすべてのデータを挿入/ロードしてからインデックスを作成する必要がありますか? (挿入を高速化するため)

  • 大きなテーブル(「トランザクション」テーブル)にパーティション分割を使用できない場合、パフォーマンスを改善するための代替オプションは何ですか? (innodb_buffer_pool_sizeなどのMySQl変数設定を除く)。 Mysqlクラスターを使用する必要がありますか? (結合もたくさんあります)

編集

これは、「トランザクション」という名前の最大のテーブルのshow create tableステートメントです。

  CREATE TABLE `transaction` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `terminal_transaction_id` int(11) NOT NULL,
 `fuel_terminal_id` int(11) NOT NULL,
 `fuel_terminal_serial` int(11) NOT NULL,
 `xboard_id` int(11) NOT NULL,
 `gas_station_id` int(11) NOT NULL,
 `operator_id` text NOT NULL,
 `shift_id` int(11) NOT NULL,
 `xboard_total_counter` int(11) NOT NULL,
 `fuel_type` int(11) NOT NULL,
 `start_fuel_time` int(11) NOT NULL,
 `end_fuel_time` int(11) DEFAULT NULL,
 `preset_amount` int(11) NOT NULL,
 `actual_amount` int(11) DEFAULT NULL,
 `fuel_cost` int(11) DEFAULT NULL,
 `payment_cost` int(11) DEFAULT NULL,
 `purchase_type` int(11) NOT NULL,
 `payment_ref_id` text,
 `unit_fuel_price` int(11) NOT NULL,
 `fuel_status_id` int(11) DEFAULT NULL,
 `fuel_mode_id` int(11) NOT NULL,
 `payment_result` int(11) NOT NULL,
 `card_pan` text,
 `state` int(11) DEFAULT NULL,
 `totalizer` int(11) NOT NULL DEFAULT '0',
 `shift_start_time` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `terminal_transaction_id` (`terminal_transaction_id`,`fuel_terminal_id`,`start_fuel_time`) USING BTREE,
 KEY `start_fuel_time_idx` (`start_fuel_time`),
 KEY `fuel_terminal_idx` (`fuel_terminal_id`),
 KEY `xboard_idx` (`xboard_id`),
 KEY `gas_station_id` (`gas_station_id`) USING BTREE,
 KEY `purchase_type` (`purchase_type`) USING BTREE,
 KEY `shift_start_time` (`shift_start_time`) USING BTREE,
 KEY `fuel_type` (`fuel_type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1665335 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT

御時間ありがとうございます、

28
mOna
  • MySQLは数十億行に対して合理的にクエリを実行できますか? -MySQLは数十億行を「処理」できます。 「合理的に」クエリに依存します。それらを見てみましょう。

  • InnoDB(MySQL 5.5.8)は数十億行の正しい選択ですか? -5.7にはいくつかの改善点がありますが、5.5はかなり優れていますが、 ほぼ6 8歳で、サポートされなくなった。

  • 数十億行に最適なデータストア-「エンジン」を意味する場合、InnoDB。

  • パフォーマンスが低下し始める前に、MySQLデータベースはどれだけ大きくなることができますか-繰り返しますが、それはクエリによって異なります。メルトダウンする1K行のテーブルを表示できます。私は、何十億行ものテーブルを使って作業してきました。

  • 大きなテーブルでMySQLが遅くなるのはなぜですか? -範囲スキャンはI/Oにつながりますが、これは遅い部分です。

  • Mysqlは約3億件のレコードを保持するテーブルを処理できますか? -また、はい。制限は約1兆行です。

  • (私の場合はinnoDBテーブルの場合)innodb_buffer_pool_sizeを増やします(たとえば、RAMの最大80%)。また、perconaブログで他のMySQLパフォーマンス調整設定をいくつか見つけました-はい

  • テーブルに適切なインデックスを作成します(クエリでEXPLANを使用)-それでは、それらを見てみましょう。このcriticalエリアでは、多くの間違いを犯す可能性があります。

  • テーブルのパーティション分割-「パーティション分割は万能薬ではありません!」 私のブログ

  • MySQLシャーディング-現在、これはDIYです

  • MySQLクラスタリング-現在、最良の答えはGaleraベースのオプション(PXC、MariaDB 10、DIY w/Oracle)です。 Oracleの「グループレプリケーション」は、実行可能な候補です。

  • パーティショニングは、FOREIGN KEYまたは「グローバル」UNIQUEをサポートしません。

  • UUIDは、あなたが話している規模で、システムを遅くするだけでなく、実際にそれを殺します。 タイプ1 UUID は回避策である可能性があります。

  • 挿入とインデックス作成の速度-バリエーションが多すぎて1つの答えを出すことができません。仮のCREATE TABLEと、データのフィード方法を見てみましょう。

  • 多数の結合-「正規化しますが、正規化し過ぎないでください。」特に、日時や浮動小数点数などの「連続的な」値を正規化しないでください。

  • ビルド summary tables

  • 1日あたり2,3百万トランザクション-230万inserts(30 /秒)の場合、パフォーマンスの問題はそれほどありません。より複雑な場合は、RAID、SSD、バッチ処理などが必要になる場合があります。

  • そのような量のデータを処理する-ほとんどのアクティビティが「最近の」行である場合、buffer_poolはアクティビティをうまく「キャッシュ」し、I/Oを回避します。アクティビティが「ランダム」の場合、MySQL(またはanyoneelse)にI/O問題が発生します。

  • データ型を縮小すると、あなたのようなテーブルで役立ちます。 fuel_typeを指定するのに4バイトが必要かどうかは疑問です。複数の1バイトアプローチがあります。

41
Rick James

数十億行を収集する場合、データを統合、処理、要約、何でもbefore保存することをお勧めします。元に戻す必要があると思われる場合は、生データをファイルに保存してください。

そうすることで、質問や懸念のほとんどが解消され、処理が高速化されます。

2
Rick James