私は、Pyramid/SQLAlchemy/Postgresql で構築され、ユーザーがいくつかのデータを管理できるようにする Web アプリケーションを持っています。そのデータは、さまざまなユーザーに対してほぼ完全に独立しています。たとえば、Alice が訪問alice.domain.com
して写真とドキュメントをアップロードでき、Bobbob.domain.com
も訪問して写真とドキュメントをアップロードできるとします。Alice は Bob によって作成されたものを見ることはなく、その逆も同様です (これは単純化された例であり、実際には複数のテーブルに多くのデータが存在する可能性がありますが、考え方は同じです)。
さて、DB バックエンドでデータを整理する最も簡単なオプションは、各テーブル (pictures
およびdocuments
) にuser_id
フィールドがある単一のデータベースを使用することです。したがって、基本的に、アリスのすべての写真を取得するには、次のようなことができます。
user_id = _figure_out_user_id_from_domain_name(request)
pictures = session.query(Picture).filter(Picture.user_id==user_id).all()
これはすべて簡単でシンプルですが、いくつかの欠点があります
- クエリを作成するときは常に追加のフィルター条件を使用することを覚えておく必要があります。そうしないと、アリスがボブの写真を見る可能性があります。
- 多くのユーザーがいる場合、テーブルが巨大になる可能性があります
- Web アプリケーションを複数のマシンに分割するのは難しい場合があります
だから、どういうわけかユーザーごとにデータを分割するのは本当にいいと思います。私は2つのアプローチを考えることができます:
同じデータベース内にアリスとボブの写真とドキュメント用に別々のテーブルを用意します (この場合、Postgres のスキーマを使用するのが正しいアプローチのようです)。
documents_alice documents_bob pictures_alice pictures_bob
次に、ダークマジックを使用して、現在のリクエストのドメインに従って、すべてのクエリをいずれかのテーブルに「ルーティング」します。
_use_dark_magic_to_configure_sqlalchemy('alice.domain.com') pictures = session.query(Picture).all() # selects all Alice's pictures from "pictures_alice" table ... _use_dark_magic_to_configure_sqlalchemy('bob.domain.com') pictures = session.query(Picture).all() # selects all Bob's pictures from "pictures_bob" table
ユーザーごとに個別のデータベースを使用します。
- database_alice - pictures - documents - database_bob - pictures - documents
これは最もクリーンなソリューションのように思えますが、複数のデータベース接続がより多くの RAM やその他のリソースを必要とし、可能な「テナント」の数が制限されるかどうかはわかりません。
それで、問題は、それはすべて理にかなっていますか? はいの場合、HTTP リクエストごとに動的にテーブル名を変更する (オプション 1 の場合)、または異なるデータベースへの接続のプールを維持し、各リクエストに正しい接続を使用する (オプション 2 の場合) ように SQLAlchemy を構成するにはどうすればよいですか?