web-dev-qa-db-ja.com

MySQLシャーディングアプローチ?

Sharding MySQLテーブルの最適なアプローチは何ですか。私が考えることができるアプローチは次のとおりです。

  1. アプリケーションレベルのシャーディング?
  2. MySQLプロキシレイヤーでのシャーディング?
  3. シャーディング用の中央検索サーバー?

この分野で興味深いプロジェクトやツールを知っていますか?

85
sheki

MySQLテーブルを分割する最良の方法は、それを行うことが完全に避けられない場合を除き、実行しないことです。

アプリケーションを作成するときは、通常、速度、開発者の速度を最大化する方法で作成します。必要な場合にのみ、レイテンシー(回答が準備できるまでの時間)またはスループット(時間単位あたりの回答数)を最適化します。

パーティションを作成し、パーティションを異なるホスト(=シャード)に割り当てるのは、これらすべてのパーティションの合計が単一のデータベースサーバーインスタンスに収まらない場合のみです(書き込みまたは読み取りの理由)。

書き込みの場合は、a)書き込みの頻度がこのサーバーディスクを永続的に過負荷にしているか、b)レプリケーションが永続的にこのレプリケーション階層で遅れるほど書き込みが多すぎます。

シャーディングの読み取りケースは、データのサイズが非常に大きく、そのワーキングセットがメモリに収まらず、データ読み取りがほとんどの場合メモリから提供されるのではなく、ディスクにヒットし始める場合です。

シャードするhaveするときのみ。


シャードする瞬間に、複数の方法でその代金を支払います:

SQLの多くは宣言型ではなくなりました。

通常、SQLでは、必要なデータをデータベースに伝え、オプティマイザーに任せて、その仕様をデータアクセスプログラムに変換します。柔軟性があり、これらのデータアクセスプログラムの作成は速度を損なう退屈な作業であるため、これは良いことです。

シャード環境では、おそらくノードAのテーブルをノードBのデータに対して結合するか、ノードAおよびBにノードよりも大きなテーブルがあり、そこからデータをノードBおよびCのデータに対して結合します。それを解決するために手動でアプリケーション側のハッシュベースの結合解決を書き始めています(またはMySQLクラスターを再発明しています)。つまり、宣言的ではなく、SQLの機能を手続き型で表現している多くのSQLになります。 (たとえば、ループでSELECTステートメントを使用している場合)。

多くのネットワーク遅延が発生しています。

通常、SQLクエリはローカルで解決でき、オプティマイザーはローカルディスクアクセスに関連するコストを認識し、そのコストを最小化する方法でクエリを解決します。

シャード環境では、ネットワークを介して複数のノードへのキー値アクセスを実行することで(ラウンドトリップごとの個別のキー検索ではなく、キーアクセスをバッチ処理することにより)、またはWHERE句の一部をそれらを適用できるノード(「条件プッシュダウン」と呼ばれる)、またはその両方。

しかし、最良の場合でも、これにはローカルの状況よりも多くのネットワークラウンドトリップが含まれ、より複雑です。特に、MySQLオプティマイザーはネットワーク遅延について何も知らないので(OK、MySQLクラスターは徐々に良くなっていますが、クラスター外のVanilla MySQLについてはまだ真実です)。

SQLの多くの表現力を失っています。

それはおそらくそれほど重要ではありませんが、外部キー制約とデータ整合性のための他のSQLメカニズムは複数のシャードにまたがることができません。

MySQLには、正常に動作する非同期クエリを許可するAPIがありません。

同じタイプのデータが複数のノードに存在する場合(ノードA、B、Cのユーザーデータなど)、これらのノードすべてに対して水平クエリを解決する必要があります(「90日間ログインしていないすべてのユーザーアカウントを検索する」以上")。データアクセス時間は、複数のノードを並列に要求でき、結果が到着時に集約される(「Map-Reduce」)場合を除き、ノードの数に比例して増加します。

そのための前提条件は、非同期通信APIです。これは、正常に機能するMySQLには存在しません。別の方法は、子プロセスの分岐と接続の多くであり、これはシーズンパスの悪夢の世界を訪れています。


シャーディングを開始すると、データ構造とネットワークトポロジがアプリケーションのパフォーマンスポイントとして表示されます。十分なパフォーマンスを得るには、アプリケーションがこれらのことを認識している必要があります。つまり、アプリケーションレベルのシャーディングのみが意味をなします。

質問は、自動断片化(たとえば、主キーをハッシュすることでどの行がどのノードに入るかを決定する)や、手動で機能的に分割する(「xyzユーザーストーリーに関連するテーブルはこれに移動する」マスター、abcおよびdef関連のテーブルはそのマスターに移動します)。

機能的シャーディングには、ユーザーストーリーに関連するすべてのテーブルがローカルで利用できるため、正しく行われた場合、ほとんどの開発者にはほとんど見えないという利点があります。これにより、可能な限り宣言型SQLのメリットを享受でき、ネットワーク間の転送数が最小限に抑えられるため、ネットワークの遅延も少なくなります。

機能的シャーディングには、1つのテーブルを1つのインスタンスより大きくすることができないという欠点があり、設計者の手動による注意が必要です。

機能的シャーディングには、既存のコードベースに対して、あまり大きくない変更をいくつか加えて比較的簡単に実行できるという利点があります。 http://Booking.com は過去数年で何度も行っており、彼らにとってはうまくいった。


それをすべて言って、あなたの質問を見て、私はあなたが間違った質問をしていると信じています、または私はあなたの問題声明を完全に誤解しています。

107
Isotopp
  1. アプリケーションレベルのシャーディング:dbShardsは、「アプリケーション対応シャーディング」を行う唯一の製品です。ウェブサイトにはいくつかの良い記事があります。定義上、アプリケーションを認識するシャーディングはより効率的になります。アプリケーションが、トランザクションを検索したり、プロキシによってリダイレクトされたりすることなく、トランザクションのどこに行くべきかを正確に知っている場合、それ自体の方が高速になります。また、誰かがシャーディングを検討している場合、速度が唯一の懸念事項ではないにしても、多くの場合、主要な懸念事項の1つです。

  2. 一部の人々はプロキシで「シャード」しますが、私の目にはシャーディングの目的に反します。別のサーバーを使用して、データの検索場所または保存場所をトランザクションに指示しています。アプリケーション対応のシャーディングにより、アプリケーションはそれ自体でどこに行くべきかを知っています。はるかに効率的です。

  3. これは、実際には#2と同じです。

10
chantheman

この分野で興味深いプロジェクトやツールを知っていますか?

この分野のいくつかの新しいプロジェクト:

  • citusdata.com
  • spockproxy.sourceforge.net
  • github.com/Twitter/gizzard/
7
btcbb

Shard-Query は、MySQL用のOLAPベースのシャーディングソリューションです。シャードテーブルと非シャードテーブルの組み合わせを定義できます。シャード化されていないテーブル(ルックアップテーブルなど)は、シャード化されたテーブルに自由に結合できます。また、シャードキーによってテーブルが結合されている限り、シャード化されたテーブルは相互に結合できます(クロスシャードまたはシャードの境界を越える自己結合はありません)。 OLAPソリューションであるため、Shard-Queryは通常、単純なクエリであっても最小応答時間が100ミリ秒以下なので、OLTPでは機能しません。 Shard-Queryは、ビッグデータセットを並行して分析するために設計されています。

OLTPシャーディングソリューションはMySQLにも存在します。クローズドソースソリューションには、 ScaleDBDBShards が含まれます。オープンソースOLTPソリューションinclude JetPantsCubrid または Flock/Gizzard (Twitterインフラストラクチャ)。

4
Justin Swanhart

もちろん応用レベル。

この本で見つけた最高のアプローチ

ハイパフォーマンスMySQL http://www.Amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

簡単な説明:データを多くの部分に分割し、各サーバーに最大50個の部分を保存できます。シャーディングの2番目に大きな問題であるリバランスを回避するのに役立ちます。それらのいくつかを新しいサーバーに移動するだけで、すべてがうまくいきます:)

購入して「mysql scaling」の部分を読むことを強くお勧めします。

3
Andrey Frolov

2018年の時点で、それに対するMySqlネイティブソリューションがあるようです。実際には少なくとも2つあります- InnoDB Cluster および NDB Cluster (商用版とコミュニティ版があります)。

MySqlコミュニティエディションを使用するほとんどの人はInnoDBエンジンに精通しているため、これを最優先事項として検討する必要があります。すぐに使用できるレプリケーションおよびパーティション化/シャーディングをサポートし、さまざまなルーティング/ロードバランシングオプションのMySqlルーターに基づいています。

テーブル作成の構文は、たとえば次のように変更する必要があります。

    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );

(これは、4つの 分割タイプ のうちの1つにすぎません)

1つの非常に重要な制限:

InnoDB外部キーとMySQLパーティションは互換性がありません。パーティション化されたInnoDBテーブルは、外部キー参照を持つことも、外部キーによって参照される列を持つこともできません。外部キーを持つ、または外部キーによって参照されるInnoDBテーブルはパーティション化できません。

2
yuranos87