sql >> データベース >  >> RDS >> Mysql

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

    完全に避けられない場合を除いて、MySQLテーブルをシャーディングして実行しないようにするための最良のアプローチ。

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

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

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

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

    持っている場合のみ シャーディングするにはそれを行います。

    シャーディングした瞬間、あなたはそれに対して複数の方法でお金を払っています:

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

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

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

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

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

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

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

    SQLの表現力を大幅に失っています。

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

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

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

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

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

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

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

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

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

    そうは言っても、あなたの質問を見ると、あなたが間違った質問をしていると思います。さもないと、あなたの問題の説明を完全に誤解しています。



    1. 同じSQLステートメントで複数のテーブルから削除することは可能ですか?

    2. Pymysql Cursor.fetchall()/ Fetchone()はなしを返します

    3. PostgreSQL:PostgreSQLでテーブルを表示する

    4. データベース呼び出しを減らしてWebサイトのパフォーマンスを向上させる