PostgreSQL: É melhor usar vários bancos de dados com um esquema cada ou um banco de dados com vários esquemas?


147

Após esse comentário em uma das minhas perguntas, estou pensando se é melhor usar um banco de dados com esquemas X ou vice-versa.

Minha situação: estou desenvolvendo um aplicativo da Web onde, quando as pessoas se registram, eu crio (na verdade) um banco de dados (não, não é uma rede social: todos devem ter acesso aos seus próprios dados e nunca ver os dados do outro usuário) .

Foi assim que usei a versão anterior do meu aplicativo (que ainda está em execução no MySQL): através da API do Plesk, para cada registro, faço:

  1. Crie um usuário de banco de dados com privilégios limitados;
  2. Crie um banco de dados que possa ser acessado apenas pelo usuário criado anterior e pelo superusuário (para manutenção)
  3. Preencher o banco de dados

Agora, precisarei fazer o mesmo com o PostgreSQL (o projeto está ficando maduro e o MySQL ... não atende a todas as necessidades).

Eu preciso ter todos os backups de bancos de dados / esquemas independentes: pg_dump funciona perfeitamente nos dois sentidos e o mesmo para os usuários que podem ser configurados para acessar apenas um esquema ou um banco de dados.

Então, supondo que você seja um usuário mais experiente do PostgreSQL do que eu, qual você acha que é a melhor solução para a minha situação e por quê?

Haverá diferenças de desempenho usando o banco de dados $ x em vez de esquemas $ x? E que solução será melhor manter no futuro (confiabilidade)?

Todos os meus bancos de dados / esquemas sempre terão a mesma estrutura!

Para a questão dos backups (usando pg_dump), talvez seja melhor usar um banco de dados e vários esquemas, despejar todos os esquemas de uma vez: a recuperação será muito simples, carregando o despejo principal em uma máquina de desenvolvimento e despeje e restaure apenas o esquema necessário: é uma etapa adicional, mas despejar todo o esquema parece mais rápido do que despejá-los um por um.

ATUALIZAÇÃO 2012

Bem, a estrutura e o design do aplicativo mudaram muito nos últimos dois anos. Ainda estou usando a one db with many schemasabordagem, mas ainda tenho um banco de dados para cada versão do meu aplicativo:

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

Para backups, estou descartando cada banco de dados regularmente e depois movendo os backups no servidor de desenvolvimento.

Também estou usando o backup PITR / WAL, mas, como eu disse antes, não é provável que precise restaurar todo o banco de dados de uma vez ... então provavelmente será descartado este ano (na minha situação não é a melhor abordagem )

A abordagem one-db-many-schema funcionou muito bem para mim desde agora, mesmo que a estrutura do aplicativo seja totalmente alterada:

Eu quase esqueci: todos os meus bancos de dados / esquemas sempre terão a mesma estrutura!

... agora, todo esquema tem sua própria estrutura que muda dinamicamente, reagindo ao fluxo de dados dos usuários.


"todos os meus bancos de dados / esquemas sempre terão a mesma estrutura!" você quer dizer que todos eles têm a mesma estrutura? Ou nunca?
Osama Al-Maadeed

Desculpe, sim, todos eles têm a mesma estrutura para sempre: se eu mudar, eu vou mudar todos eles;)
Strae

Se você possui 1000 clientes, isso significa que você deve atualizar o esquema 1000?
Joshua Partogi

@ jpartogi: sim, mas eu tenho que atualizar apenas a estrutura das tabelas, não os dados.
Strae

Então, o que você fez finalmente? Porém, uma pergunta, embora o desempenho de consultas etc. possa ser controlada por espaços de tabela, esquemas que resultam em desempenho equivalente de multi-db vs multi-schema, qualquer impacto nos logs do WAL ???
Kapil

Respostas:


113

Um "esquema" do PostgreSQL é aproximadamente o mesmo que um "banco de dados" do MySQL. Ter muitos bancos de dados em uma instalação do PostgreSQL pode ser problemático; ter muitos esquemas funcionará sem problemas. Então você definitivamente quer ir com um banco de dados e vários esquemas dentro desse banco de dados.


33
Este. O Postgres não permite que você faça consultas nos bancos de dados, o que pode ser bastante irritante.
matt b

81
"Ter muitos bancos de dados em uma instalação do PostgreSQL pode ficar problemático" - por favor, esclareça; é problemático em geral ou neste caso específico, e por quê?
Akaihola 20/12/2009

33
"O caso de uso mais comum para o uso de vários esquemas em um banco de dados é a criação de um aplicativo de software como serviço em que cada cliente tenha seu próprio esquema. Embora essa técnica pareça atraente, recomendamos vivamente que ela tenha causado muitos casos de . problemas operacionais Por exemplo, mesmo um número moderado de esquemas (> 50) pode afetar seriamente o desempenho da ferramenta de banco de dados do Heroku instantâneos" devcenter.heroku.com/articles/heroku-postgresql
Neil McGuigan

16
@ NeilMcGuigan: Curiosamente, essa parece ser a conclusão oposta à resposta (aceita) de kquinn.
carbocation

8
Ter um banco de dados com muitos esquemas tornará praticamente impossível despejar um único esquema deles. Estou executando um único banco de dados do postgres com mais de 3000 esquemas e o pg_dump apenas falha com um erro de falta de memória se você tentar despejar um único esquema. Gostaria de saber se isso seria diferente se eu tivesse 3000 bancos de dados.
Machisuji

27

Definitivamente, irei para a abordagem de um db-muitos-esquemas. Isso me permite despejar todo o banco de dados, mas restaurar apenas um com muita facilidade, de várias maneiras:

  1. Despejar o banco de dados (todo o esquema), carregar o despejo em um novo banco de dados, despejar apenas o esquema necessário e restaurar novamente no banco de dados principal.
  2. Despejar o esquema separadamente, um por um (mas acho que a máquina sofrerá mais dessa maneira - e estou esperando 500 esquemas!)

Caso contrário, pesquisando no Google, vi que não há procedimento automático para duplicar um esquema (usando um como modelo), mas muitos sugerem o seguinte:

  1. Criar um esquema de modelo
  2. Quando precisar duplicar, renomeie-o com novo nome
  3. Despejá-lo
  4. Renomeie-o novamente
  5. Restaurar o despejo
  6. A mágica está pronta.

Eu escrevi duas linhas em Python para fazer isso; Espero que eles possam ajudar alguém (em 2 segundos, código escrito, não o use na produção):

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

Eu diria, vá com vários bancos de dados e vários esquemas :)

Esquemas no PostgreSQL são muito parecidos com pacotes no Oracle, caso você esteja familiarizado com eles. Os bancos de dados visam diferenciar conjuntos inteiros de dados, enquanto os esquemas são mais parecidos com entidades de dados.

Por exemplo, você pode ter um banco de dados para um aplicativo inteiro com os esquemas "UserManagement", "LongTermStorage" e assim por diante. "UserManagement" conteria a tabela "User", além de todos os procedimentos armazenados, gatilhos, sequências etc. necessários para o gerenciamento do usuário.

Bancos de dados são programas inteiros, esquemas são componentes.


4
... e, portanto, terei 1 banco de dados com os esquemas: $ customer1_user_schema, $ customer2_user_schema, $ customer3_user_schema, $ customer1_documents_schema, $ customer2_documents_schema, $ customer3_documents_schema? Mh ... não parece uma maneira confiável ... e o desempenho? E o código do meu aplicativo (será php e python)? tantos esquemas ..
Strae

7
@Trae: Estou lendo isso como: cada cliente tem seu banco de dados customer1_database, customer2_database e dentro desses bancos de dados você tem user_schema, documents_schema.
frankhommers

6

No contexto do PostgreSQL, recomendo usar um banco de dados com vários esquemas, pois você pode (por exemplo) UNION ALL entre esquemas, mas não entre bancos de dados. Por esse motivo, um banco de dados é realmente completamente isolado de outro banco de dados, enquanto os esquemas não são isolados de outros esquemas no mesmo banco de dados.

Se você, por algum motivo, precisar consolidar dados entre esquemas no futuro, será fácil fazer isso em vários esquemas. Com vários bancos de dados, você precisaria de várias conexões db, coletar e mesclar os dados de cada banco de dados "manualmente" pela lógica do aplicativo.

Os últimos têm vantagens em alguns casos, mas, na maior parte, acho que a abordagem de um banco de dados com vários esquemas é mais útil.


4

Vários esquemas devem ser mais leves que vários bancos de dados, embora não seja possível encontrar uma referência que confirme isso.

Mas se você realmente deseja manter as coisas muito separadas (em vez de refatorar o aplicativo Web para que uma coluna "cliente" seja adicionada às suas tabelas), você ainda pode querer usar bancos de dados separados: eu afirmo que você pode fazer restaurações mais facilmente de banco de dados de um cliente específico dessa maneira - sem incomodar os outros clientes.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.