MySQL のパーティショニング / シャーディング / 分割 - どの方法を選択するか?
-
09-06-2019 - |
質問
当社の InnoDB データベースは約 70 GB ですが、今後 2 ~ 3 年で数百 GB に増加すると予想しています。データの約 60 % は 1 つのテーブルに属します。現在、64 GB の RAM を搭載したサーバーを使用しているため、データベースは非常にうまく機能しており、データベースのほぼ全体がメモリに収まりますが、データ量が大幅に増加する将来が心配です。現在、テーブル (特にデータの大部分を占めるテーブル) を分割する何らかの方法を検討しており、最適な方法は何だろうと考えています。
私が現在知っているオプションは次のとおりです
- バージョン 5.1 に付属する MySQL パーティショニングの使用
- データのパーティショニングをカプセル化するある種のサードパーティ ライブラリを使用する (休止状態のシャードなど)
- アプリケーション内で自分たちで実装する
私たちのアプリケーションは J2EE と EJB 2.1 に基づいて構築されています (いつか EJB 3 に切り替えることを願っています)。
何を提案しますか?
編集 (2011-02-11):
ただのアップデート:現在、データベースのサイズは 380 GB、「大きな」テーブルのデータ サイズは 220 GB、インデックスのサイズは 36 GB です。したがって、テーブル全体はメモリに収まりませんが、インデックスはメモリに収まります。
システムは引き続き (同じハードウェア上で) 正常に動作しており、データのパーティション分割についてまだ検討中です。
編集 (2014-06-04):もう 1 つの更新:データベース全体のサイズは 1.5 TB、「大きな」テーブルのサイズは 1.1 TB です。サーバーを 128 GB RAM を搭載した 4 プロセッサ マシン (Intel Xeon E7450) にアップグレードしました。システムは引き続き正常に動作しています。次に計画しているのは、大きなテーブルを別のデータベース サーバーに配置し (ソフトウェアに必要な変更はすでに行っています)、同時に 256 GB RAM を備えた新しいハードウェアにアップグレードすることです。
この設定は 2 年間続くと考えられています。その場合、最終的にシャーディング ソリューションの実装を開始するか、1 TB の RAM を搭載したサーバーを購入して、しばらくは使い続ける必要があります。
編集 (2016-01-18):
それ以来、大きなテーブルを別のサーバー上の独自のデータベースに配置しました。現在、このデータベースのサイズは約 1.9 TB、他のデータベース (「大きな」データベースを除くすべてのテーブル) のサイズは 1.1 TB です。
現在のハードウェア設定:
- HP ProLiant DL 580
- 4 x Intel(R) Xeon(R) CPU E7-4830
- 256 GB RAM
この設定ではパフォーマンスは問題ありません。
解決
IO/メモリに制約されると思われる場合、パーティショニングは役に立たないと思います。いつものように、最初にベンチマークを行うと、最適な方向を見つけるのに役立ちます。64 GB のメモリを搭載した予備のサーバーがない場合は、いつでもベンダーに「デモ ユニット」を依頼できます。
1 つのクエリの集計レポートを期待しない場合は、シャーディングを使用することをお勧めします。大きなテーブルだけでなくデータベース全体をシャーディングすると仮定します。エンティティ全体をまとめておくことが最善です。まあ、モデルがうまく分割できればともかく。
他のヒント
42 GB のテーブルがメモリに収まらなくなると、間違いなく問題が発生し始めます。実際、メモリに収まらなくなるとすぐに、パフォーマンスが急速に低下します。テストする 1 つの方法は、そのテーブルを RAM の少ない別のマシンに置き、パフォーマンスがどの程度低下するかを確認することです。
まず、テーブルの一部を別の物理ボリュームに移動しない限り、テーブルを分割することはそれほど問題ではありません。
これは間違いです。パーティショニング (MySQL 5.1 の機能を使用するか、MERGE テーブルを使用する同じこと) により、テーブルが同じドライブ上にある場合でも、パフォーマンスが大幅に向上します。
例として、日付範囲を使用して大きなテーブルに対して SELECT クエリを実行しているとします。テーブル全体の場合、クエリはテーブル全体を強制的にスキャンすることになります (そのサイズでは、インデックスを使用しても速度が低下する可能性があります)。パーティション分割の利点は、クエリが絶対に必要なパーティションでのみ実行されることです。各パーティションのサイズが 1 GB で、クエリを実行するためにクエリが 5 つのパーティションにアクセスするだけで済む場合、MySQL では、結合された 5 GB テーブルの方が、モンスターの 42 GB バージョンよりもはるかに簡単に処理できます。
自問する必要があるのは、データをどのようにクエリするかということです。クエリがデータの特定のチャンクにのみアクセスする必要がある可能性がある場合 (つまり、日付範囲または ID 範囲など)、ある種のパーティショニングが有益であることがわかります。
MySQL 5.1 のパーティショニングにはまだバグがあり、特に MySQL が正しいキーを選択することに関連していると聞きました。MERGE テーブルでも同じ機能を提供できますが、オーバーヘッドが若干多くなります。
お役に立てば幸いです...頑張ってください!
これは、実際の巨大なデータ フローの例で MySql パーティショニングが何ができるかを示す好例です。
あなたのケースに役立つことを願っています。
少し前の Microsoft ArcReady イベントで、役立つと思われるスケーリング パターンに関するプレゼンテーションを見ました。あなたはできる スライドを見る それはオンラインで。
私なら、MariaDB InnoDB + パーティション (クエリに応じてキーまたは日付のいずれか) を選択します。
これを実行したところ、データベースの問題はなくなりました。
MySQL は数秒で MariaDB に置き換えることができます。データベース ファイルはすべて同じままです。
まず、テーブルの一部を別の物理ボリュームに移動しない限り、テーブルを分割することはそれほど問題ではありません。
次に、移動する必要があるのは、必ずしも物理サイズが最大のテーブルであるとは限りません。大きなテーブルはほぼ一定のままであるか、データを追加するだけである一方で、より小さなテーブルではより多くのアクティビティが発生する場合があります。
何をするにしても、自分で実行しないでください。データベース システムに処理させます。
大きなテーブルは何をするのですか?
分割する場合は、いくつかのオプションがあります。
- データベース システムを使用して分割します (それについてはあまり知りません)
- 行ごとに分割します。
- 列ごとに分割します。
行ごとに分割できるのは、データを簡単にチャンクに分割できる場合のみです。例えば何かのようなもの ベースキャンプ 完全に別々の複数のアカウントを持っています。アカウントの 50% を 1 つのテーブルに保持し、50% を別のマシン上の別のテーブルに保持することができます。
列による分割は、行サイズに大きなテキスト フィールドまたは BLOB が含まれる状況に適しています。(たとえば) ユーザー画像と巨大なテキスト ブロックを含むテーブルがある場合、その画像をまったく別のテーブルにファームすることができます。(別のマシン上で)
ここで正規化を破りますが、それほど多くの問題は発生しないと思います。
いつものように、最初にベンチマークを行うと、最適な方向を見つけるのに役立ちます。
ほとんどの人がそう言うので、最終的にはその薬を飲まなければいけないと思います...
おそらく、最終的にはその大きなテーブルを分割することになるでしょう。おそらく、2 番目のサーバーを考える前に、別のハードディスクに置くことをお勧めします。MySQL を使用して実行するのが最も便利なオプションです。それができるなら、それをしてください。
しかし
実際のところ、すべてはデータベースがどのように使用されるかによって決まります。統計。