私はPyramid/SQLAlchemy/Postgresqlで構築され、ユーザがいくつかのデータを管理でき、そのデータはユーザごとにほとんど完全に独立しているWebアプリケーションを持っています。アリスはalice.domain.com
にアクセスして画像や文書をアップロードし、ボブはbob.domain.com
にアクセスし、画像や文書をアップロードすることもできます。アリスはボブが作成したものは一切見ることができません。逆の場合はです(これは単純な例ですが、実際には複数のテーブルに多数のデータがあるかもしれませんが、アイデアは同じです)。SQLAlchemyを使ったマルチテナント
さて、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()
のようなもの。これは、すべての簡単でシンプルです、しかし、いくつかの欠点がある
- 私がそうでなければ、アリスがボブのパイを見て、クエリを作成するときは、常に追加のフィルタ条件を使用することを覚えておく必要がありますctures;
- テーブルが
- 巨大な成長する可能性が多くのユーザーが存在する場合だから私はそれを何とかあたりのデータを分割するために、本当にいいだろうと思っています複数のマシン
の間でWebアプリケーションを分割するのが難しいかもしれ-ユーザー。私は2つのアプローチを考えることができます。
:は、同じデータベース内の別ののテーブルアリスのためのとボブの写真や文書を持っている(PostgresのSchemasが、この場合に使用する正しいアプローチのようです)現在のリクエストのドメインに応じて
documents_alice documents_bob pictures_alice pictures_bob
、その後、いくつかの黒魔術を使って、「ルート」1や他のテーブルにすべてのクエリ:
_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を構成するにはどうすればよいですか?
:http://stackoverflow.com/questions/9298296/をsqlalchemy-support-of-postgres-schemas –
@CraigRinger:はい、受け入れられた回答の "SET search_path TO ..."がうまくいけば、それはオプション#1の解決策になります。ありがとう。 – Sergey
バットからデータベースをシャードするのを避けたい場合は、sqlalchemy.orgの[Pre-Filtered Queries](http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery)のレシピがあります。および[Global Filters](http://www.sqlalchemy.org/trac/wiki/UsageRecipes/GlobalFilter)を参照してください。 –