Qual é o desempenho do PostgreSQL com um grande número de bancos de dados?

9

Temos um aplicativo da Web cuja arquitetura exige que qualquer usuário registrado (uma empresa, na verdade) seja isolado do outro, ou seja, executarei o mesmo aplicativo da Web 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, 10-20K bancos de dados? Quão bem?

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

Desde já, obrigado.

Carlos
fonte

Respostas:

10

No extremo inferior, basicamente se resume a "você pode dizer absolutamente que não possui dados compartilhados?" Diferente 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 for com bancos de dados separados (pelo menos não sem dblink).

Se você possui algum dado compartilhado, o "esquema" do postgresql é semelhante ao que o mysql chama de "banco de dados" . Você pode CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);. Você poderia criar um esquema para cada cliente, o usuário do cliente teria seu esquema pela primeira vez em seu caminho de pesquisa, e seria concedido permissões para que o usuário do Cliente Um teriam acesso ao clientae os publicesquemas (e suas tabelas).

Seu problema será que, no final de # de clientes, cada tabela é armazenada como um arquivo. Portanto, se você usar um banco de dados por cliente, um esquema por cliente ou usar algo parecido ${client}_customercom os nomes de suas tabelas, poderá é provável que atinja os limites do filedescriptor com 10 mil clientes, mesmo que você tenha apenas uma tabela por cliente (mais um filedescriptor por conexão). Obviamente, você pode ajustar o número máximo de descritores de arquivos do kernel em tempo real usando sysctl, mas o limite por processo (ulimit) exigirá a reinicialização do postgresql se você o definir muito baixo na primeira vez.

A alternativa é ter "uma grande tabela" com uma coluna de cliente que identifique a qual cliente essa linha pertence (idealmente, por nome de usuário, se você tiver um usuário por cliente, isso facilita muito as coisas abaixo). Ao não conceder nenhum acesso a essa tabela pelos clientes, você pode criar visualizações específicas do cliente (ou usar session_userpara identificar o cliente atual). As atualizações não podem ser feitas diretamente através de uma exibição. Você precisaria ter funções definidas para inserir / atualizar / excluir na tabela (um conjunto de funções por cliente ou usar session_user) com as funções usadas SECURITY DEFINERpara executar como um usuário especial com permissão para inserir / atualizar / excluir nas tabelas (observação : session_useré usado porque userecurrent_user são baseados no contexto atual e, dentro de uma função DEFINER DE SEGURANÇA, esse sempre seria o usuário que definiu a função).

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

Eu direi que optei por bancos de dados separados para cada cliente aqui (adicionamos servidores para manter o sistema utilizável, transferindo bancos de dados de clientes para novos servidores conforme necessário, para que nunca cheguemos a 10 mil bancos de dados em um servidor). Eu tive que restaurar os dados de clientes individuais de backups para depuração ou devido a erros do usuário regularmente, algo que seria um pesadelo absoluto no design de "uma grande mesa". Além disso, se você pretende vender a personalização do seu produto para seus clientes, o design de "uma grande mesa" pode acabar atrapalhando você na capacidade de personalizar o modelo de dados.

DerfK
fonte
Olá DerfK. Não posso usar a abordagem "uma mesa grande" devido ao motivo que você declarou. Mesmo que hoje, os modelos de dados sejam os mesmos para todos os usuários, não podemos garantir que eles sempre serão os mesmos. Além disso, eu não sabia sobre os limites absolutos do banco de dados no PSQL (como temos alguns dados compartilhados). Acho que deixei as abordagens de nomeação de esquemas e tabelas à esquerda. Na sua experiência, quão difícil é gerenciar esse número de bancos de dados (mesmo em servidores diferentes)?
Carlos
@ Eduardo A maior dificuldade que tenho com isso é garantir que, quando o modelo de dados precisar mudar para todos, isso seja feito. Algum dia adaptaremos algo como o sistema do Rails para gerenciar alterações no modelo de dados, até então eu tenho um script que percorre os clientes e executa o mesmo comando em todos os bancos de dados. Como não compartilhamos dados, tudo foi bem fácil. Se você optar por um banco de dados com vários esquemas, ainda poderá despejar um esquema de cliente por vez usando pg_dump -n(certifique-se de despejar o esquema comum também!) Para listar o esquema: psql -Eentão\dn
DerfK:
@ Eduardo não projeta para recursos que você não tem o direito. Se fosse esse o caso, meu carro seria um submarino, repeliria ursos e seria capaz de voar para a lua. Existem muitos padrões sólidos de design de banco de dados que permitem começar com uma tabela grande e adicionar recursos adicionais, conforme necessário. A chave é perguntar a si mesmo o que você precisa hoje e o que sua equipe de operações poderá oferecer suporte com base em projeções de crescimento.
Jeremias Peschka
@ DerfK, qual é a pilha da web que você usa hoje?
Carlos Carlos
@ Jeremiah, você tem um bom argumento. Você tem experiência com aplicativos multitenantes?
Carlos Carlos
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 Web e houver um usuário compartilhado do aplicativo Web no banco de dados, você não terá isolado seus dados de maneira diferente da utilização de 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ê procura, sem a dor de cabeça administrativa de gerenciar mais de 10.000 bancos de dados em qualquer número de servidores.

Pessoalmente, eu executei uma configuração semelhante em um único servidor de banco de dados usando nada além de procedimentos armazenados parametrizados, atingindo um único banco de dados. Se você pode garantir que o único acesso ao banco de dados é através de procedimentos armazenados, não há perigo de combinação de dados nos resultados.

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

  1. ficando sem descritores de arquivo aberto ( ulimit -n) no 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
Jeremiah Peschka
fonte
E quão difícil seria fazer backup e restaurar os dados de um cliente? É mais fácil fazer isso com procedimentos armazenados ou com esquemas? Como você afirmou, o design do aplicativo usa apenas um usuário compartilhado para se conectar ao banco de dados. Inicialmente, a abordagem de múltiplos bancos de dados foi considerada por questões de gerenciamento, e não por segurança.
Carlos
Procedimentos armazenados parametrizados não protegem contra nada além de injeções de SQL. Se um desses procedimentos a SELECT * WHERE clientId = 3, você tem um vazamento de segurança.
precisa saber é o seguinte