SQL Server 2016、シャードを備えたマルチテナントシステム、またはテナントごとに個別のデータベースを介してテナントを分離する必要がありますか?


12

ユースケースを考えます:

  • テナントデータはクロストークしてはいけません。あるテナントは別のテナントのデータを必要としません。
  • 各テナントには、大量の履歴データが潜在的に含まれている可能性があります。
  • SQL ServerはAWS EC2インスタンスでホストされます。
  • 各テナントは地理的に離れています。
  • PowerBI Embeddedなどのサードパーティの視覚化ツールを使用する意図があります。
  • データ量は時間とともに増加すると予想されます
  • システムのコストには制約があります。
  • ソリューションは、24時間365日の実稼働DBAなしで保守可能でなければなりません。
  • ソリューションは水平方向にスケーリングできる必要があります。
  • テナントの総数は50未満です

推奨されるアーキテクチャは何ですか?このユースケースのリファレンス実装はありますか?多くの人がエンタープライズソフトウェア開発のためにすでにこの問題に直面していると思います。

これは、マルチテナントデータベースアーキテクチャで増加するテナントの処理とは異なる状況だと思います。その質問で言及されているユースケースは、より多くのテナントを扱っていますが、これは非常に少数の大きなテナントを持つこととは非常に異なります。ここで説明したアーキテクチャは、ここで解決策になる可能性があります。これは、私がもっと知りたいことです。

回答:


16

シャーディングの落とし穴は、アプリケーションが照会するシャードを知る必要があることです。一般的に、これはクライアントのようなものでシャーディングすることによって行われます。古いブログ投稿の1つを、回答として使用するように調整します。

多くのクライアント向けのアプリケーションを構築する場合、データベースを設計する2つの一般的な方法があります。

  • オプションA:すべてのクライアントを同じデータベースに配置する
  • オプション2:クライアントごとに1つのデータベースを構築する

すべてのクライアントを同じデータベースに配置する

簡単です。スキーマの一番上にClientテーブルを追加し、ClientUsersテーブルを追加して、自分のデータのみが表示されるようにします。

このアプローチの利点:

より簡単なスキーマ管理。開発者がアプリケーションの新しいバージョンをデプロイする場合、1つのデータベースでスキーマを変更するだけで済みます。異なる顧客が同期しなくなったり、間違ったバージョンになったりする心配はありません。

簡単なパフォーマンスチューニング。インデックスの使用状況と統計を1か所で確認し、改善を簡単に実装し、すべてのクライアントですぐに効果を確認できます。数百または数千のデータベースでは、わずかな変更でも調整が困難な場合があります。プロシージャキャッシュの内容を確認し、アプリケーション全体でどのクエリまたはストアドプロシージャが最も集中しているのかを特定できますが、クライアントごとに個別のデータベースを使用している場合は、異なる実行プラン間でクエリの使用を集約するのが難しくなります。

外部APIを簡単に構築できます。製品を構築するために部外者にデータベース全体へのアクセスを許可する必要がある場合、すべてのデータが単一のデータベースにあれば簡単にできます。APIが複数のサーバー上の複数のデータベースからのデータのグループ化を処理する必要がある場合、開発およびテスト時間が追加されます。(一方、「複数のサーバー」ということは、1つのデータベースからすべてのルールに至るシナリオの制限を示唆し始めます。1つのデータベースは通常、負荷が1つのデータベースサーバーのみに影響することを意味します。) 、PowerBIを使用すると、全員を1つのデータベースに入れると、接続の管理がはるかに簡単になります。

より簡単な高可用性と災害復旧。心配する必要があるのが1つのデータベースだけであれば、データベースミラーリング、ログ配布、レプリケーション、およびクラスタリングを管理するのは本当に簡単です。インフラストラクチャを迅速に構築できます。

各クライアントを独自のデータベースまたはシャードに入れる

まだクライアントのリストが必要ですが、今ではディレクトリになります-各クライアントについて、それが存在するシャードも追跡します。起動時に、アプリはこのテーブルをクエリし、RAMにキャッシュします。クライアントのデータが必要な場合、そのシャード(データベースとサーバー)に直接接続します。

このアプローチの利点:

簡単な単一クライアントの復元。クライアントは信頼できないミートバッグです。(私のものを除いて、信頼できるミートバッグです。)あらゆる種類の「おっと」瞬間があるので、すべてのデータを特定の時点に戻したいのです。同じテーブル内の他のクライアントデータ。単一クライアントデータベースのシナリオでの復元は非常に簡単です。クライアントのデータベースを復元するだけです。誰も影響を受けません。

より簡単なデータのエクスポート。クライアントは、データを手に入れるのが大好きです。彼らは、恐ろしいベンダーのロックインシナリオを回避し、いつでも自分のデータを取り出すことができることを知り、独自のレポートを作成したいというセキュリティを求めています。各クライアントのデータが独自のデータベースに分離されているため、単純に独自のデータベースバックアップのコピーを提供できます。データエクスポートAPIを作成する必要はありません。

より簡単なマルチサーバースケーラビリティ。アプリケーションが単一のサーバーから得られる以上のパワーを必要とする場合、複数のサーバー間でデータベースを分割できます。また、地理的に負荷を分散し、アジアまたはヨーロッパのサーバーをクライアントに近づけることもできます。

クライアントごとのパフォーマンスチューニングが容易になりました。一部のクライアントが異なる機能またはレポートを使用する場合、全員のデータサイズを増大させることなく、それらのクライアント専用のインデックスまたはインデックス付きビューの特別なセットを構築できます。確かに、ここにはいくつかのリスクがあります。クライアント間でスキーマの違いを許容することにより、コードの展開を少し危険にしただけで、パフォーマンス管理をより難しくしました。

より簡単なセキュリティ管理。データベースごとに1人のユーザーでセキュリティを適切にロックダウンしている限り、クライアントXがクライアントYのデータにアクセスすることを心配する必要はありません。ただし、すべてのユーザーに対して単一のログインを使用する場合は、この懸念に実際には対処していません。

より簡単なメンテナンスウィンドウ。 顧客が世界中に散在しているグローバル環境では、グループまたはゾーンで行うことができれば、保守のために顧客をオフラインにする方が簡単です。

どちらがあなたに合っていますか?

正しい選択は1つではありません。自社の長所と短所を知る必要があります。2つのクライアントを例としてみましょう。

A社は、ハードウェアパフォーマンスの調整に優れています。彼らは本当に、ハードウェアのパフォーマンスの最後のビットを絞り出すのが得意であり、12〜18か月のサイクルでSQL Serverハードウェアを交換することを気にしません。(4〜6か月ごとにWebサーバーを更新します!)彼らのアキレス腱は、極端なコンプライアンスとセキュリティ要件です。監査のニーズは非常に高く、数十台のサーバー上の数千のデータベースでこれらの要件を管理するよりも、単一のサーバー、単一のデータベースに防弾制御を実装する方が簡単です。1つのデータベース、1つのサーバー、多くのクライアントを選択しました。

会社2は開発プラクティスに優れています。数千のデータベースにまたがるスキーマの変更とコードの展開を管理することは、それらの問題ではありません。彼らは世界中にクライアントを持ち、それらのクライアントのクレジットカード取引を24時間処理しています。地理的に負荷を分散する機能が必要であり、世界中のサーバーを12〜18か月ごとに交換したくない。クライアントごとに1つのデータベースを選択し、オフショアクライアント用にSQL Serverをアジアとヨーロッパに導入し始めたため、成果を上げています。


「PowerBIを使用すると、全員を1つのデータベースに入れると、接続の管理がはるかに簡単になります」。今組込みPowerBIは、行レベルのセキュリティを持っていないので、1つのデータベース内のすべてのテナントを持つことは、このユースケースについていくつかの疑問を引き起こしている、以下を参照してください。community.powerbi.com/t5/Developer/...が、この情報の光の中で、あなたは言い換えをしてもらえこれまたは代替案を提案するか、私の理解を修正しますか?
DS

また、この2つの提案の間にここでの違いについて詳しく説明できた「独自のデータベースまたはシャードで各クライアントを置く」
DS

複数のデータベースに展開しなければならないということは、あなたが思っているほど悪くはないということです。2017年には、1、5、または900個のデータベースへの変更を非常に簡単に展開できる多くのオプションがあります。また、特定の顧客に例外がある場合、それらは通常、それらが一般的なコードに干渉しないようにそれらのデータベースに導入できます。
アーロンバートランド

5

他の回答ではまだ見たことのない、もう1つの考慮事項。

単一のデータベースで多くのテナントを考慮した設計を行うと、後で柔軟性が得られます。後でロード/スケールアウト/セキュリティ/地理的位置の要求が発生した場合、テナントは新しいインスタンスに正しいDBを復元することで作成できる別のデータベースを用意する必要があります。他のテナントのデータは、配置されているメカニズムによって保護されています。時代遅れのデータは、時間の許す限り、古いデータベースと新しいデータベースの両方から断片的に削除できます。

その逆は当てはまりません。多くのワンテナントデータベースを統合するには、かなり多くの作業が必要になります。


4

マルチテナントモデルを正規化に違反している場合でもはるかに簡単にする1つのプラクティスは、テナントのすべてのテーブルに列を含めることです。TenantIDと呼ぶことができます。このように、データベースに対して実行されるすべてのクエリは、すべてのテーブルのTenantIDでフィルタリングでき、データベースパーティション分割を使用して各テナントのデータを分離し、パーティションを揃えることでクエリを高速化できます。この方法ですべてのテナントを1つのデータベースに格納する方がはるかに簡単です。

*常に正規化が壊れるわけではありませんが、可能です。たとえばPersonPersonAddressテーブルとテーブルがある場合。Personテーブルには、必要がありますTenantID, PersonID主キーとして。PersonAddressテーブルには、必要がありますTenantID, PersonID, AddressTypeID、私は示唆しています何と主キーとして。

通常PersonIDはそれで十分でしょう。なぜなら、それをPersonテーブルに結合してを見つけることができるからですTenantTenantIDより細いキーが機能する場合でも、後続のすべてのテーブルに繰り越すことをお勧めします。

私の理解では、他のデータから派生する可能性のある情報をテーブルに持ち越すことは、正規化を破ると考えられていました。ただし、おそらくシンキーを使用するのがベストプラクティスにすぎません。


おかげで、私は提案に同意し、その上に追加するために、このフィールドTenantIDはGUIDではなく整数型でなければならないことに言及したいと思います。パフォーマンスのためにそのように燃やされました。
DS

3
ただし、TenantIDを子テーブルに持ち込むことを選択した場合でも、これを行う必要はありませんが、キーが広くても正規化が「壊れている」ことを意味しません。IDENTITY(より広いキー)よりもGUIDを選択するのと同様に、正規化を壊すことも、サロゲートを使用する代わりに、より広い自然キーを選択することもありません。
アーロンバートランド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.