2011-12-08 30 views
5

有許多公司發佈信息的應用程序。每家公司的數據都是獨立的 - 沒有數據重疊。,是分區還是多個數據庫更高效?

性能,明智的,是它更好地:

  • 保持對每個表的每一行的公司標識,並各指標使用它呢?
  • 分區根據該公司ID
  • 分區並創建一個用戶的每個表訪問各個公司,以確保安全
  • 創建多個數據庫,每一個公司持久連接

基於web的應用。

我的想法:

  • 新皮克連接是昂貴的,所以一個數據庫中創建只有一個字典的副本似乎比200更高效左右
  • 多個數據庫不太新的連接
  • 從程序員錯誤肯定更安全
  • 如果應用程序規格應該改變,所以公司共享,多個數據 基地將難以實施

回答

14

我建議搜索有關多租戶設計的PostgreSQL郵件列表信息。這裏有很多討論,答案歸結爲「取決於」。在保證隔離,性能和可維護性之間,每種方式都有權衡。

一種常見的方法是使用單個數據庫,但每個客戶使用一個schema(名稱空間),每個客戶在每個模式中具有相同的表結構,並且對於所有數據都是相同的數據使用共享或通用模式。 PostgreSQL模式就像一個MySQL「數據庫」,您可以跨不同模式查詢,但默認情況下它們是隔離的。通過獨立模式中的客戶數據,您可以使用search_path設置,通常通過ALTER USERcustomername SET search_path = 'customerschema, sharedschema'來確保每位客戶都能看到他們的數據並且只能看到他們的數據。

對於額外的保護,您應該REVOKEALL FROM SCHEMA customerschema FROM public然後GRANTALL ON SCHEMA customerschema TO thecustomer所以他們是唯一一個與它的任何訪問,做同樣的每個其表的。連接池,然後可以與具有沒有向任何客戶模式GRANT版訪問,但有SET ROLE權,成爲客戶的任何一個固定的用戶帳戶登錄。 (這樣做是通過給予他們每個客戶角色的成員身份,使用NOINHERIT設置權限,因此權限必須通過SET ROLE明確聲明)。連接應立即SET ROLE到它目前正在運行的客戶。這將允許您避免爲每個客戶建立新連接的開銷,同時保持強大的保護,防止程序員錯誤導致訪問錯誤的客戶數據。只要該池在將連接移交給下一個客戶端之前執行DISCARD ALL和/或RESET ROLE,那麼這將給予您非常強大的隔離,而不會讓每個用戶的單獨連接受挫。

如果你的Web應用程序環境中沒有一個像樣的連接池內置的(比如,你正在使用PHP和持久連接),那麼你真的需要把good connection pool到位PG和Web服務器之間無論如何,因爲太多的後端連接會傷害你的表現。 PgBouncerPgPool-II是最好的選擇,並且可以在連接切換時輕鬆地爲您做好DISCARD ALLRESET ROLE的準備工作。

這種方法的主要缺點是維護很多表的開銷,因爲您爲每個客戶克隆了一組非共享表。隨着客戶數量的增長,它會相加,直到在自動清理運行期間檢查的表的數量開始變得昂貴,並且根據數據庫中的表總數進行縮放的任何操作變慢。如果您想要在同一個數據庫中擁有數千或數萬個客戶,那麼這更成爲一個問題,但我強烈建議您在提交之前使用虛擬數據對此設計進行一些縮放測試。

理想的方法很可能是使用自動行級安全控制元組可視性的單個表,但不幸的是,這是PostgreSQL尚不具備的。由於SEPostgreSQL的工作增加了合適的基礎架構和API,它看起來很順利,但它不在9.1中。

+0

非常感謝! (對不起,最近一直在和MySQL一起工作,它讓我腦子死了。)模式應該是多個數據庫的選項 - 事實上,它已經用於其他項目。連接後設置角色的好主意。一直在使用set path,但是兩者的組合最好。 –

+0

是的,設置角色讓您可以使用數據庫級別的安全性,而不會產生太多的痛苦。這很棒。 –

+0

...並且記住要使用像PgPool-II或PgBouncer這樣體面的連接池,如果你在Web服務器端使用基本的東西,比如持久連接的PHP。如果您使用的是類似於Java服務器的服務器,並且它自己的連接池在服務器中,則不需要。 –

相關問題