PostgreSQLは多数のデータベースでどの程度うまく機能しますか?


9

登録ユーザー(実際には会社)を他のユーザーから分離する必要があるアーキテクチャを持つWebアプリケーションがあります。つまり、同じWebappを同じデータモデルで実行しますが、顧客ごとに異なるデータセットを使用します。

したがって、Postgresで顧客ごとに異なるデータベースを作成することを検討しました。このソリューションは、たとえば10〜20Kのデータベースに拡張できますか?いかに良く?

誰かがこれのためのより良い解決策を持っていますか?

前もって感謝します。

回答:


10

ローエンドでは、基本的には「共有データがないと絶対に言えますか」ということになります。mysqlとは異なり、データベースはpostgresqlの絶対的な境界です。SELECT zip_code FROM common.city_zip WHERE city=...別のデータベースを使用している場合はできません(少なくともなしではできませんdblink)。

共有データがある場合、postgresqlの「スキーマ」は、mysqlが「データベース」と呼ぶものに似ています。できCREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);ます。クライアントごとにスキーマを作成し、そのクライアントのユーザーは最初に検索パスにスキーマを持ち、クライアントAのユーザーがclientapublicスキーマ(およびそのテーブル)にアクセスできるように権限が付与されます。

問題は、クライアント数の上限では、各テーブルがファイルとして保存されるため、クライアントごとに1つのデータベースを使用する場合でも、クライアントごとに1つのスキーマを使用する${client}_customer場合でも、テーブル名に何かを使用する場合でも、クライアントごとに1つのテーブルしかない場合でも(接続ごとに1つのファイル記述子)、たとえ10kのクライアントでファイル記述子の制限に達する可能性があります。もちろん、カーネルのファイル記述子の最大数をsysctlを使用してオンザフライで調整できますが、プロセスごとの制限(ulimit)を最初に低く設定しすぎると、postgresqlを再起動する必要があります。

別の方法は、行がどのクライアントに属しているかを識別するクライアント列を持つ「1つの大きなテーブル」を作成することです(理想的には、クライアントごとに1人のユーザーがいる場合はユーザー名によって、これによりLOTの下のものが簡単になります)。クライアントによるこのテーブルへのアクセスをまったく許可しないことにより、クライアント固有のビューを作成できます(またはsession_user現在のクライアントを識別するために使用できます)。ただし、ビューから直接更新を行うことはできません。テーブルへの挿入/更新/削除の権限を持つ特別なユーザーとして実行するためにsession_user使用SECURITY DEFINERする関数を使用して、テーブルへの挿入/更新/削除(クライアントごとに1セットの関数またはを使用する関数)を定義する関数が必要です(注:session_user使用されているためusercurrent_user 現在のコンテキストに基づいており、SECURITY DEFINER関数内では、これは常に関数を定義したユーザーになります。

パフォーマンスの点では、fdの問題を超えて、10000個のクライアントに相当するデータを含む1つの大きなテーブルがあるのに対して、postgresqlの10000個のデータベースで何が起こるかを正直に知りません。適切なインデックス設計は、大きなテーブルのクエリが遅くなることを防ぎます。

ここでは、クライアントごとに個別のデータベースを使用したと言います(システムを使用可能な状態に保つためにサーバーを追加し、必要に応じてクライアントデータベースを新しいサーバーに移動するため、1つのサーバーで10kデータベースに到達することはありません)。デバッグや定期的なユーザーエラーのために、バックアップから個々のクライアントのデータを復元する必要がありました。これは、「1つの大きなテーブル」の設計では絶対的な悪夢となるものです。また、製品のカスタマイズをクライアントに販売しようとする場合、「1つの大きなテーブル」の設計では、データモデルをカスタマイズする機能にまで踏み込んでしまう可能性があります。


こんにちは、DerfK。あなたが述べた理由により、「1つの大きなテーブル」アプローチを使用できません。今日でも、データモデルはすべてのユーザーで同じですが、常に同じであるとは限りません。また、PSQLの絶対的なデータベース境界については知りませんでした(共有データがいくつかあるため)。スキーマとテーブルの命名方法は残したと思います。あなたの経験では、この数のデータベースを(異なるサーバーでも)管理するのはどれほど難しいですか
カルロス

@Eduardo私がこれで抱えている最大の問題は、データモデルをすべての人のために変更する必要があるときに、それが確実に行われるようにすることです。いつか、データモデルへの変更を管理するためにRailsのシステムのようなものを採用します。それまでは、クライアントをループしてすべてのデータベースで同じコマンドを実行するスクリプトができました。共有データをまったく使用しないため、他のすべては非常に簡単です。複数のスキーマを持つ1つのdbを使用する場合でも、pg_dump -nスキーマをリストするために(必ず共通スキーマもダンプしてください!)を使用して、一度に1つのクライアントスキーマをダンプできます。psql -E次に\dn
DerfK

@Eduardoは、適切でない機能を設計しません。もしそうだとしたら、私の車は潜水艦でクマを撃退し、月へ飛ぶことができるでしょう。大きなテーブルから始めて、必要に応じて追加の機能を追加できる、充実したデータベース設計パターンがたくさんあります。重要なのは、今日必要なものと、成長予測に基づいて運用チームがサポートできるものを自問することです。
エレミアペシュカ

@DerfK、今日使用しているWebスタックは何ですか?
カルロス

@ジェレミア、あなたは良い点を持っています。マルチテナントアプリケーションの経験はありますか?
カルロス

3

アプリケーションの詳細がなければ、この設定から追加のセキュリティが得られるとは言いがたいです。各クライアントがWebアプリに接続し、Webアプリからデータベースへの共有ユーザーがいる場合、単一のモノリシックデータベースを使用する場合とは異なる方法でデータを分離していません。適切にパラメーター化されたストアドプロシージャを介してデータにアクセスすると、任意の数のサーバーで10,000以上のデータベースを管理するという管理上の問題なしに、探しているレベルの分離が提供されます。

個人的には、データベース化された単一のデータベースにパラメーター化されたストアドプロシージャを使用して、同様のセットアップを単一のデータベースサーバーで実行しました。データベースへの唯一のアクセスがストアドプロシージャを介したものであることを保証できれば、結果にデータが混在する危険はありません。

デザインを進めたい場合は、主に次の点に注意してください。

  1. ulimit -nホストOS で開いているファイル記述子が不足している()
  2. さまざまなクエリパターンに合わせて10,000以上のデータベースを調整する
  3. さまざまなセキュリティ上の懸念がある10,000以上のデータベースの管理(バックアップと潜在的な復元、サーバーに障害が発生した場合に本当に10,000以上のデータベースを復元しますか?)
  4. 10,000以上のデータベースにわたる変更のロールアウト

また、クライアントのデータのバックアップと復元はどれほど難しいでしょうか。ストアドプロシージャまたはスキーマを使用する方が簡単ですか。すでに述べたように、アプリの設計では、データベースに接続するために1人の共有ユーザーしか使用しません。当初、複数データベースのアプローチは、セキュリティではなく、管理上の考慮事項として考慮されていました。
Carlos

パラメータ化されたストアドプロシージャは、SQLインジェクション以外には何も保護しません。これらの手順のいずれかがを実行する場合SELECT * WHERE clientId = 3、セキュリティリークがあります。
ミケロビ2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.