PostgreSQL:使用多个数据库,每个数据库有一个模式,还是一个数据库有多个模式,更好?


147

在对我的问题之一发表评论之后,我在考虑使用具有X模式的数据库是否更好,反之亦然。

我的情况:我正在开发一个Web应用程序,当人们注册时,我会创建(实际上)一个数据库(不,它不是社交网络:每个人都必须有权访问自己的数据,而从不查看其他用户的数据) 。

这就是我以前的应用程序版本(仍在MySQL上运行)所使用的方式:通过Plesk API,对于每次注册,我都这样做:

  1. 创建具有有限权限的数据库用户;
  2. 创建一个只能由先前创建的用户和超级用户访问的数据库(用于维护)
  3. 填充数据库

现在,我需要对PostgreSQL做同样的事情(该项目正在日趋成熟,而MySQL ...不能满足所有需求)。

我需要使所有数据库/方案备份独立:pg_dump可以在两种方式下完美运行,并且对于可以配置为仅访问一个模式或一个数据库的用户而言,pg_dump可以完美地工作。

因此,假设您比我更有经验的PostgreSQL用户,那么您认为什么是对我而言最好的解决方案,为什么?

使用$ x数据库而不是$ x模式会有性能差异吗?哪种解决方案将来会更好维护(可靠性)?

我所有的数据库/方案都将始终具有相同的结构!

对于备份问题(使用pg_dump),最好使用一个数据库和多个模式,一次转储所有模式:恢复将非常简单,将主转储加载到开发计算机中,然后仅转储和还原所需的模式:是另外一个步骤,但是转储所有模式似乎比逐个转储它们要快。

2012年更新

好吧,在过去的两年中,应用程序的结构和设计发生了很大的变化。我仍在使用该one db with many schemas方法,但是仍然为我的应用程序的每个版本提供一个数据库:

Db myapp_01
    \_ my_customer_foo_schema
    \_ my_customer_bar_schema
Db myapp_02
    \_ my_customer_foo_schema
    \_ my_customer_bar_schema

对于备份,我会定期转储每个数据库,然后将备份移至开发服务器上。

我也在使用PITR / WAL备份,但是,正如我之前说过的那样,我不太可能必须立即还原所有数据库 ...因此它可能会在今年被淘汰(在我看来,这不是最好的方法) )。

从现在开始,即使应用程序结构已完全更改,“单db-多次模式”方法对我来说也非常有效:

我几乎忘记了:我所有的数据库/方案都将始终具有相同的结构!

...现在,每个模式都有其自己的结构,该结构可动态响应用户数据流。


“我所有的数据库/方案都将具有相同的结构!” 您是说它们都具有相同的结构吗?还是永远不会?
奥萨马·阿马德

抱歉,是的,它们永远都具有相同的结构:如果我更改一个,我将全部更改;)
Strae,2009年

如果您有1000个客户,那意味着您必须更新1000个架构?
Joshua Partogi 2010年

@jpartogi:是的,但是我必须只更新表结构,而不是数据。
Strae 2010年

那么,您最后想做什么呢?尽管有一个问题,尽管查询的性能等可以由表空间,模式控制,从而导致多数据库与多模式的等效性能,但对WAL日志有任何影响???
卡皮尔2012年

Answers:


113

PostgreSQL的“模式”与MySQL的“数据库”大致相同。在PostgreSQL上安装许多数据库可能会出现问题。具有许多模式将毫无问题。因此,您肯定要使用一个数据库和该数据库中的多个架构。


33
这个。Postgres不允许您跨数据库查询,这很烦人。
马特b

81
“在PostgreSQL安装上有很多数据库会出现问题” –请澄清;在一般情况下还是在此特定情况下有问题,为什么?
akaihola

33
“在数据库中使用多个模式的最常见用例是构建一个软件即服务应用程序,其中每个客户都有自己的模式。虽然这种技术似乎很引人注目,但我们强烈建议不要这样做,因为它导致了许多情况下,例如,即使是中等数量的模式(> 50)也会严重影响Heroku数据库快照工具的性能。“ devcenter.heroku.com/articles/heroku-postgresql
Neil McGuigan

16
@NeilMcGuigan:有趣的是,这似乎与kquinn(接受的)答案相反。
carbocation

8
但是,拥有一个具有许多模式的数据库将使几乎不可能转储这些数据库的单个模式。我正在运行具有3000多个模式的单个postgres数据库,如果尝试转储单个模式,pg_dump会因内存不足错误而失败。我想知道如果使用3000个数据库,这是否会有所不同。
Machisuji '17

27

毫无疑问,我将采用“单数据库多方案”方法。这使我可以转储所有数据库,但是可以通过许多方式非常轻松地还原其中一个数据库:

  1. 转储数据库(所有架构),将转储加载到新数据库中,仅转储我需要的架构,然后还原回主数据库中。
  2. 分别逐一转储架构(但是我认为计算机将以这种方式遭受更多损失-我期望有500个架构!)

否则,在Google上四处搜寻,我发现没有自动程序可以复制模式(使用一个作为模板),但是许多人建议这样做:

  1. 创建模板架构
  2. 需要复制时,用新名称重命名
  3. 转储它
  4. 重新命名
  5. 恢复转储
  6. 魔术完成了。

我在Python中写了两行来做到这一点。我希望他们能帮助某人(用2秒的代码编写,不要在生产中使用它):

import os
import sys
import pg

# Take the new schema name from the second cmd arguments (the first is the filename)
newSchema = sys.argv[1]

# Temperary folder for the dumps
dumpFile = '/test/dumps/' + str(newSchema) + '.sql'

# Settings
db_name = 'db_name'
db_user = 'db_user'
db_pass = 'db_pass'
schema_as_template = 'schema_name'

# Connection
pgConnect = pg.connect(dbname= db_name, host='localhost', user= db_user, passwd= db_pass)

# Rename schema with the new name
pgConnect.query("ALTER SCHEMA " + schema_as_template + " RENAME TO " + str(newSchema))

# Dump it
command = 'export PGPASSWORD="' + db_pass + '" && pg_dump -U ' + db_user + ' -n ' + str(newSchema) + ' ' + db_name + ' > ' + dumpFile
os.system(command)

# Rename back with its default name
pgConnect.query("ALTER SCHEMA " + str(newSchema) + " RENAME TO " + schema_as_template)

# Restore the previous dump to create the new schema
restore = 'export PGPASSWORD="' + db_pass + '" && psql -U ' + db_user + ' -d ' + db_name + ' < ' + dumpFile
os.system(restore)

# Want to delete the dump file?
os.remove(dumpFile)

# Close connection
pgConnect.close()

14

我会说,使用多个数据库和多个模式:)

如果您熟悉PostgreSQL,则Schema与Oracle中的软件包非常相似。数据库旨在区分整个数据集,而模式则更像数据实体。

例如,您可以为整个应用程序使用一个数据库,其架构为“ UserManagement”,“ LongTermStorage”等。这样,“ UserManagement”将包含“ User”表以及用户管理所需的所有存储过程,触发器,序列等。

数据库是整个程序,模式是组件。


4
...所以我将拥有1个数据库,其中包含以下架构:$ customer1_user_schema,$ customer2_user_schema,$ customer3_user_schema,$ customer1_documents_schema,$ customer2_documents_schema,$ customer3_documents_schema?嗯...似乎不是可靠的方法...性能如何?那我的应用程序代码(将是php和python)呢?如此多的模式..
Strae

7
@Strae:我的读法是:每个客户都有它的数据库customer1_database,customer2_database,在这些数据库中,您有user_schema,documents_schema。
frankhommers

6

在PostgreSQL上下文中,建议您将一个数据库与多个模式一起使用,例如,您可以(例如)跨模式而不是跨数据库使用UNION ALL。因此,数据库实际上与另一个数据库完全隔离,而架构与同一数据库中的其他架构则没有隔离。

如果出于某种原因您将来不得不跨架构整合数据,那么在多个架构上执行此操作将很容易。对于多个数据库,您将需要多个数据库连接,并通过应用程序逻辑“手动”收集和合并每个数据库中的数据。

后者在某些情况下具有优势,但是对于主要部分,我认为单数据库多方案方法更有用。


4

尽管我找不到参考文献来证实这一点,但许多模式应该比许多数据库更轻量。

但是,如果您真的想使事情保持非常独立(而不是重构Web应用程序,以便在表中添加“客户”列),则可能仍要使用单独的数据库:我断言您可以更轻松地还原这样一来,一个特定客户的数据库-不会打扰其他客户。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.