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


88

MySQLテーブルのシャーディングに最適なアプローチは何ですか。私が考えることができるアプローチは次のとおりです:

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

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

回答:


115

MySQLテーブルをシャーディングするための最善の方法は、やむをえず避けられない場合を除き、行わないことです。

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

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

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

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

シャードする必要があるときだけ、それを行います。


シャーディングした瞬間に、複数の方法で支払います。

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

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

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

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

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

シャーディング環境では、クエリはネットワークを介して複数のノードにキーと値のアクセスを実行することで(できれば、ラウンドトリップごとに個別のキールックアップではなくバッチキーアクセスを使用して)、またはWHERE句の一部をノードの前方にプッシュすることで解決されます。適用される(「条件プッシュダウン」と呼ばれる)、またはその両方。

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

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

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

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

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

その前提条件は非同期通信APIであり、MySQLには適切に機能する形では存在しません。代替案は、子プロセスの多くの分岐と接続であり、シーズンパスでサックの世界を訪れます。


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

自動シャーディングを行う場合(たとえば、主キーをハッシュすることによってどの行がどのノードに入るかを判別する場合)、または手動で機能的に分割する場合(「xyzユーザーストーリーに関連する表は、マスター、abcおよびdef関連のテーブルはそのマスターに移動します」)。

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

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

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


そうは言っても、あなたの質問を見て、あなたが間違った質問をしていると思います、または私はあなたの問題のステートメントを完全に誤解しています。


2
これは良い答えです。ただし、シャーディングは実際には大量のアプリケーションにのみ必要であり、何らかの種類の収益を生み出している可能性があることを指摘しておきます。サードパーティのシャーディングアプリケーションは、結合、クロスシャードトランザクションなどに関するすべての懸念を処理します。また、適切なものを取得すると、「リレーショナル」データベースの整合性が維持されます。他のアプリケーションもそうですが、データベースをキーと値のペアに単純に変換し、SQLの目的を無効にします。
chantheman

3
データがネットワーク全体に分散しており、レイテンシに起因する待機がないためにレイテンシまたは不整合が生じているという事実を隠すことに成功している、商用または非共有のシャーディングアプリケーションをまだ見つけていません。シャーディングしている場合、アプリケーションがそれに気づき、変更が必要になります。あなた自身もそれをコントロールしているかもしれません。特効薬はありませんが、ヘビ油がたくさんあります。
Isotopp

1
dbShardsをチェックアウトする必要があります。追加した「シャード」の数ごとに線形よりもスケーリングが向上します。アプリケーション側で変更を加える必要があるとしても、ごくわずかですが、そうです、アプリケーションは違いを知りません。ODBCまたはJDBCの場合と同じように、トランザクションを送信および取得するだけです。dbShardsでは、トランザクションをより詳細に制御する必要がある場合、シャードヒントも許可されます。dbShardsに、読み取りまたは書き込みを行うシャードを正確に指示できます。
chantheman 2011

1
@Gigalaまあ、広義に関係なく、このように明確に定義された回答を作成するのに時間を費やす必要もありませんが、この回答が役に立ったことがわかったので、それができてうれしいです。回答する際に、ユーザーが「ボックスの外側で考える」ことをしないようにしないでください。
mewm

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

  2. 一部の人々はプロキシで「シャーディング」しますが、私の目にはシャーディングの目的に反します。別のサーバーを使用して、トランザクションのどこにデータを見つけるか、どこに保存するかを伝えています。アプリケーション対応のシャーディングにより、アプリケーションは独自にどこへ行くべきかを認識します。はるかに効率的です。

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


dbShardsは本番環境でどこで使用されていますか?また、オープンソースではありません。
シェキ

また、プロキシがDBまたはストアではなくハッシュに基づいてルックアップする場合、アプローチ2と3は異なる場合があります。
シェキ

1
dbShardsはさまざまなクライアントで運用されていますが、オープンソースではありません。良いオープンソースのシャーディング製品が見つかるとは思いません。そして、はい、ハッシュをルックアップとして使用できることは正しいですが、その場合でも、トランザクションをデータベースに送るために、もう1つ「停止」する必要があります。そのため、「アプリケーション対応」のシャーディングはほとんど常に高速になります。
chantheman 2011

しかし、先ほど述べたように、関係の整合性を維持するシャーディングアプリケーションを入手できれば、良好な状態になります。dbShardsについては、私が知っているのはそれだけなので、これについて言及します。また、そのため、書き込みと読み取りの速度を直線的にスケーリングします。4つの「シャード」を追加するか、1つのMySQLサーバーを4つに分割すると、4倍の速度で実行されます。
chantheman

7

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

このスペースのいくつかの新しいプロジェクト:

  • citusdata.com
  • spockproxy.sourceforge.net
  • github.com/twitter/gizzard/

5

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

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


3

もちろんアプリケーションレベル。

私がこの本で見つけた今までで最高のアプローチ

高性能MySQL http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

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

購入して「mysqlスケーリング」の部分を読むことを強くお勧めします。


あなたが推薦した本は8年前のものです...それは今日のテクノロジーに関連するシャーディングをカバーしていますか?
ラフィアン、2012年

1
mysqlをスケーリングするためのいくつかの基本的なアプローチについて説明します。AFAIKはmysqlのスケーリングで何も変更しませんでした。同じアプリレベルのシャーディングとレプリケーションの手法が今日広く使用されています。
Andrey Frolov、2012年

私は間違っている可能性がありますが、過去1週間にわたってこれについて大量の調査を行っており、mySQL自体が過去8年間で特にパーティション分割とキャッシュに関して多くの変更を加えたようです。今年リリースされた新しいバージョンがあります:amazon.com/High-Performance-MySQL-Optimization-Replication/dp/…まだ読んでいませんが、利用可能な新しいレプリケーションモデルをカバーしていると思います。
NateDSaint

4
本..なぜここでそれを説明しないのか。
DDD、2017年

2

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

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テーブルはパーティション化できません。


日付範囲がある場合は、すべてのパーティションPARTITION BY HASH(YEAR...)がスキャンされることに注意してください。ああ。
リックジェームズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.