長い投稿でごめんなさい!
〜30個のテーブル(InnoDBエンジン)を含むデータベースがあります。これらのテーブルのうち、「トランザクション」と「シフト」の2つだけが非常に大きくなります(最初のテーブルには150万行、シフトには23k行あります)。これですべてが正常に動作し、現在のデータベースサイズに問題はありません。
ただし、同様のデータベース(同じデータ型、設計など)がありますが、はるかに大きくなります。たとえば、「トランザクション」テーブルには約10億レコードがあります(1日あたり約230万トランザクション)そして、MySQLでこのような量のデータをどのように扱うべきかを考えていますか? (読み取りと書き込みの両方が集中します)。 Mysql(より具体的にはInnoDBエンジン)が何十億ものレコードでうまく機能するかどうかを確認するために、関連する多くの投稿を読みましたが、まだいくつか質問があります。私が読んだ関連記事のいくつかは、次のとおりです。
非常に大きなテーブルのパフォーマンスを改善するためにこれまでに理解したこと:
innodb_buffer_pool_size
を増やします(たとえば、RAMの最大80%)。また、他のMySQLパフォーマンス調整設定もいくつか見つけました ここperconaブログここに私の質問/混乱があります:
パーティションについては、使用すべきかどうか疑問があります。一方、多くの人は、テーブルが非常に大きい場合にパフォーマンスを改善することを提案しました。一方で、クエリのパフォーマンスが向上せず、クエリの実行速度が向上しないと言う記事を多く読んでいます(例: 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
御時間ありがとうございます、
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バイトアプローチがあります。
数十億行を収集する場合、データを統合、処理、要約、何でもbefore保存することをお勧めします。元に戻す必要があると思われる場合は、生データをファイルに保存してください。
そうすることで、質問や懸念のほとんどが解消され、処理が高速化されます。