web-dev-qa-db-ja.com

マルチクライアントアプリケーションに単一または複数のデータベース設定を使用する必要がありますか?

私はPHP会社のワークフローとプロジェクト管理を容易にすることを目的とするアプリケーションに取り組んでいます。 BasecampGoPlan のようなものを考えてみましょう。

データベースに関して、最善のアプローチが何かはわかりません。単一のデータベースを使用して、各テーブルにクライアント固有の列を追加する必要がありますか、それとも新しいクライアントごとにデータベースを作成する必要がありますか?重要な要素は自動化です。新しいクライアントを作成するのが非常に簡単になるようにしたいと思います(おそらく、自分でサインアップする可能性を広げます)。

1つのデータベースを使用することで考えられる短所:

  • 拡張性の欠如
  • セキュリティの問題(バグは最初から存在すべきではありません

これについてどう思いますか?上記の企業がどのソリューションを選択する可能性が最も高いかについて、アイデアはありますか?

61
Aron Rotteveel

私は通常、ClientIDをすべてのテーブルに追加し、1つのデータベースを使用します。ただし、データベースのスケーリングは通常難しいため、一部またはすべてのクライアントで異なるデータベースインスタンスで実行することも可能にします。

これにより、1つのデータベースに多数の小さなクライアントを配置し、別のサーバーに大きなクライアントを配置できます。

ただし、保守性の重要な要素は、すべてのデータベースでスキーマを同一に保つことです。クライアント固有のスキーマを導入せずにバージョニングを管理するのに十分な頭痛があります。

37
idstam

JoelとJeffが同じ質問について語るStackoverflowポッドキャストを聞いてください。 Joelは、自社のソフトウェアのホストされたバージョンを提供した経験について話しています。 DB全体にクライアントIDを追加すると、設計とコードが複雑になり(誤ってWHERE句に追加するのを忘れていないのですか)、クライアント固有のバックアップなどのホスティング機能が複雑になると彼は指摘します。

エピソード#20または#21でした(詳細については、トランスクリプトを確認してください)。

34
Philipp Schmid

私の見解では、それはあなたの見込み顧客ベースに依存するでしょう。 Archのライバルが両方ともシステムを使用している状況に陥る可能性がある場合は、個別のデータベースを使用することをお勧めします。また、DBMSが複数のデータベースを実装する方法にも依存します。各データベースにインフラストラクチャの個別のコピーがある場合、それは単一のデータベース(またはDBMSの変更)を示唆しています。インフラストラクチャの1つのコピーで複数のデータベースを処理できる場合は、個別のデータベースを使用します。

データベースのバックアップを考えてください。顧客Aは「私のデータのコピーを送ってください」と言っています。単一のデータベースを共有する場合よりも、個別のデータベース設定ではるかに簡単です。顧客を削除することを考えてください。繰り返しになりますが、個別のデータベースを使用するとはるかに簡単です。

(たとえば、「データベース」と「サーバーインスタンス」を構成するものについては、DBMS間で大きな違いがあるため、「インフラストラクチャ」の部分は口当たりがいいです。Add:質問には「mysql」というタグが付けられます」なので、おそらくそれらの考えは完全に関連しているわけではありません。)

追加:もう1つの問題-単一のデータベースに複数の顧客がいる場合、すべてのSQLクエリで、正しい顧客のデータが選択されていることを確認する必要があります。つまり、SQLは書き込みと読み取りが難しくなり、DBMSはデータの処理により多くの労力を費やす必要があり、インデックスは大きくなります。そして、実際には別のデータベースを使用します多くの目的のための顧客。

明らかに、StackOverflow(例として)には、ユーザーごとに個別のデータベースはありません。私たちはすべて同じデータベースを使用しています。しかし、もしあなたが異なる会社のために会計システムを運営しているなら、データベースを共有することは(会社にとって、そしておそらく法的人々にとっては)受け入れられないと思います。

22
  • [〜#〜] development [〜#〜]迅速な開発のために、顧客ごとにデータベースを使用します。顧客のデータのバックアップ、復元、削除がどれほど簡単になるか考えてください。または、使用量を測定/監視/請求します。自分でコードを書く必要はなく、データベースプリミティブを使用するだけです。

  • [〜#〜] performance [〜#〜]パフォーマンスのために、すべての人にデータベースを使用します。接続プーリング、共有メモリ、キャッシングなどについて考えてください。

  • [〜#〜] business [〜#〜]ビジネスプランに多数の小規模な顧客がいる場合(hotmailを考える)、おそらく単一のDBで作業する必要があります。また、登録、削除、データ移行などのすべての管理タスクを完全に自動化し、使いやすいインターフェースで公開します。数十人から最大数百人の大規模顧客を計画している場合は、顧客ごとに1つのDBで作業し、顧客サポートスタッフが操作できるシステム管理スクリプトを配置できます。

13
flybywire

次の screencast は、salesforce.comでの実行方法を説明しています。彼らは、各テナントのデータを識別する特別な列OrgIdを持つ1つのデータベースを使用します。それ以外にもたくさんあるので、これを調べる必要があります。私は彼らのアプローチで行きます。

MSDNには、もう1つの素晴らしい 記事 があります。共有または分離アプローチを使用する必要がある場合について詳しく説明します。すべてのテナントで共有DBを使用することは、セキュリティに重要な影響を与えることに注意してください。また、すべてのテナントが同じDBオブジェクトを共有する場合、[行レベルのセキュリティ]を使用することをお勧めします-使用するDBMSによっては(MSで可能であることは確かです) SQL ServerとOracle、おそらくIBM DB2にも)。 mySQLの行レベルのセキュリティ のようなトリックを使用して、同様の結果(ビュー+トリガー)を実現できます。

12

マルチテナンシーの場合、パフォーマンスは通常、テナント間で共有するために管理するリソースを増加させます。

http://en.wikipedia.org/wiki/Multitenancy

したがって、可能であれば、単一のデータベースを使用してください。アプリケーションにすべてのアクセス制御を実装できるため、セキュリティの問題はバグによってのみ発生することに同意します。一部のデータベースでは、ビューを注意深く使用することにより、データベースアクセスコントロールを引き続き使用できます(そのため、認証されたユーザーごとに異なるビューを取得できます)。

拡張性を提供する方法もあります。たとえば、拡張属性(テナント、ベースレコード、および拡張属性IDをキーとする)を持つ単一のテーブルを作成できます。または、テナントごとの拡張テーブルを作成して、各テナントが独自の拡張スキーマを持つようにすることもできます。

10

マルチテナントデータベースを設計する場合、通常は3つのオプションがあります。

  1. テナントごとに1つのデータベースがある
  2. テナントごとに1つのスキーマがある
  3. すべてのテナントに同じテーブルを共有させる

選択するオプションは、スケーラビリティ、拡張性、分離に影響します。これらの影響は、さまざまな StackOverflowの質問 およびデータベースの記事で広く議論されています。

実際には、3つの設計オプションのそれぞれが-十分な労力で-規模、テナント間で異なるデータ、および分離に関する質問に対処できます。決定は、構築するプライマリディメンションによって異なります。サマリー:

  • 大規模に構築する場合:すべてのテナントに同じテーブルを共有させる
  • 分離のために構築している場合:テナントごとに1つのデータベースを作成します

たとえば、 Google およびSalesforceは最初のパターンに従い、テナントに同じテーブルを共有させます。一方、Stackoverflowは2番目のパターンに従い、テナントごとに1つのデータベースを保持します。 2番目のアプローチも、ヘルスケアなどの規制産業ではより一般的です。

決定は、データベース設計を最適化しているプラ​​イマリディメンションによって決まります。 SaaS規模のデータベース の設計に関するこの記事では、トレードオフについて説明し、PostgreSQLのコンテキストで要約を提供します。

5
ozgune

考慮すべきもう1つの点は、ある企業のデータを別の企業のデータから分離する法的義務がある場合があることです。

4
da5id

クライアントごとにデータベースを用意することは、通常、適切に拡張されません。 MySQL(およびおそらく他のデータベース)は、テーブルごとにリソースを開いたままにします。これは、1つのインスタンスで1万以上のテーブルには適していません。これは、大規模なマルチテナントの状況で発生します。

もちろん、このレベルに到達する前に他の問題を引き起こす他の問題がある場合、これは関係がないかもしれません。

さらに、アプリケーションがますます大きくなるにつれて、マルチテナントアプリケーションの「シャーディング」は、おそらく最終的に行うべき正しいことです。

ただし、シャーディングとは、テナントごとに1つのデータベース(またはインスタンス)を意味するのではなく、シャードまたはシャードのセットごとに1つを意味します。おそらく本番環境で、自分に合った適切なチューニングパラメータを見つける必要があります(したがって、最初からかなりチューニング可能である必要があります)。

€保証できません。

4
MarkR

単一のデータベースから始めて、アプリケーションの成長に応じてデータベースを分割できます。これを行う場合、私がお勧めする点がいくつかあります。

1)簡単に分割できるようにデータベースを設計します。たとえば、顧客がデータを共有する場合、データが各データベース間で簡単に複製されることを確認してください。

2)データベースが1つしかない場合は、別の物理サーバーにバックアップされていることを確認してください。フェイルオーバーが発生した場合、トラフィックをこの他のサーバーに戻しても、データはそのまま残ります。

0
jjriv