O desempenho do PostgreSQL com um grande número de bancos de dados?

7

Temos um aplicativo da web cuja arquitetura exige que qualquer usuário registrado (uma empresa, na verdade) seja isolado do outro, ou seja, eu executarei o mesmo webapp com os mesmos modelos de dados, mas com conjuntos de dados diferentes para cada cliente.

Então, pensamos em criar um banco de dados diferente no Postgres para cada cliente. Essa solução pode ser dimensionada para, digamos, bancos de dados de 10 a 20 mil? Quão bem?

Alguém tem uma solução melhor para isso?

Obrigado antecipadamente.

    
por EdMelo 26.04.2011 / 22:25

2 respostas

8

No final, basicamente se resume a "você pode dizer com absoluta certeza que não tem dados compartilhados?" Ao contrário do mysql, o banco de dados é um limite absoluto no postgresql. Você não pode SELECT zip_code FROM common.city_zip WHERE city=... se você for com bancos de dados separados (pelo menos não sem dblink ) .

Se você tiver algum dado compartilhado, o "esquema" do postgresql é semelhante ao que o mysql chama um "banco de dados" . Você pode CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...); . Você criaria um esquema para cada cliente, o usuário desse cliente teria seu esquema primeiro em seu caminho de pesquisa e as permissões seriam concedidas para que o usuário do Cliente A tivesse acesso aos clienta e public schemas (e suas tabelas ).

Seu problema será que, na extremidade alta de # de clientes, cada tabela é armazenada como um arquivo, portanto, se você usa um banco de dados por cliente, um esquema por cliente ou usa algo como ${client}_customer para seus nomes de tabelas, você provavelmente encontrará os limites do filedescriptor com clientes 10k, mesmo que você só tinha uma tabela por cliente (mais um filodescriptor por conexão). É claro, você pode ajustar o número máximo de descritores de arquivos do kernel durante a execução usando sysctl, mas o limite por processo (ulimit) exigirá a reinicialização do postgresql se você defini-lo como muito baixo na primeira vez.

A alternativa é ter "uma tabela grande" com uma coluna de cliente que identifica a qual cliente essa linha pertence (idealmente, pelo nome de usuário se você tiver um usuário por cliente, isso torna as coisas abaixo de um LOTE mais fácil). Ao não conceder nenhum acesso a essa tabela pelos clientes, você pode criar exibições específicas do cliente (ou usar session_user para identificar o cliente atual). Atualizações não podem ser feitas diretamente através de uma visão, no entanto. Você precisaria ter funções definidas para inserir / atualizar / excluir na tabela (um conjunto de funções por cliente ou usando session_user ) com as funções usando SECURITY DEFINER para executar como um usuário especial com permissão para inserir / atualizar / delete nas tabelas (nota: session_user é usado porque user e current_user são baseados no contexto atual, e dentro de uma função SECURITY DEFINER, este sempre seria o usuário que definiu a função).

Em termos de desempenho, além da questão fd, eu sinceramente não sei o que aconteceria com 10000 bancos de dados no postgresql, em vez de ter uma tabela grande com 10000 clientes de dados. O design adequado do índice deve impedir que a tabela grande seja lenta para consultar.

Eu vou dizer que eu usei bancos de dados separados para cada cliente aqui (nós adicionamos servidores para manter o sistema utilizável, mudando bancos de dados clientes para novos servidores conforme necessário, então nunca chegaremos a 10k bancos de dados em um servidor). Eu tive que restaurar dados de clientes individuais de backups para depuração ou devido a erro do usuário em uma base regular, algo que seria um pesadelo absoluto no design de "uma grande mesa". Além disso, se você pretende vender a personalização de seu produto para seus clientes, o design de "uma grande tabela" pode acabar atrapalhando você quanto à capacidade de personalizar o modelo de dados.

    
por 27.04.2011 / 00:58
3

Sem mais detalhes sobre seu aplicativo, é difícil dizer que você obterá segurança adicional com essa configuração. Se cada cliente se conectar ao aplicativo da Web e houver um usuário compartilhado do aplicativo da Web no banco de dados, você não terá isolado seus dados de maneira diferente de usar um único banco de dados monolítico. O acesso aos seus dados por meio de procedimentos armazenados adequadamente parametrizados fornecerá o nível de isolamento que você está procurando, sem a dor de cabeça administrativa de gerenciar mais de 10.000 bancos de dados em qualquer número de servidores.

Eu pessoalmente executei uma configuração semelhante em um único servidor de banco de dados usando nada mais do que procedimentos armazenados parametrizados em um único banco de dados. Se você puder garantir que o único acesso ao banco de dados é por meio de procedimentos armazenados, não há perigo de mistura de dados nos resultados.

Se você quiser avançar com seu design, aqui estão minhas principais preocupações:

  1. esgotando os descritores de arquivos abertos ( ulimit -n ) no seu sistema operacional host
  2. ajustando mais de 10.000 bancos de dados para diferentes padrões de consulta
  3. administrando mais de 10.000 bancos de dados com diferentes preocupações de segurança (backups e restaurações em potencial, você realmente deseja restaurar mais de 10.000 bancos de dados se houver uma falha no servidor?)
  4. implementando alterações em mais de 10.000 bancos de dados
por 26.04.2011 / 22:34