O desempenho não é pior, necessariamente. Como o artigo explica, existem condições específicas que tornam a abordagem do esquema melhor ou pior, dependendo do design do aplicativo e da carga de trabalho. Deixe-me explicar as compensações das abordagens "esquema de locatário" versus "tabela compartilhada":
esquema de locatário é melhor quando você tem um número relativamente pequeno de inquilinos bastante grandes. Um exemplo disso seria um aplicativo de contabilidade, com apenas usuários de assinatura paga. As coisas que o tornam a opção de melhor desempenho para você incluem:
- um pequeno número de locatários com muitos dados cada
- um esquema relativamente simples sem muitas tabelas por locatário
- necessidade de personalizar os esquemas de alguns locatários
- capacidade de usar funções de banco de dados por locatário
- requisito para migrar os dados de um locatário de um servidor para outro
- capacidade de ativar um servidor de aplicativos dedicado em sua nuvem para cada locatário
As coisas que o tornam uma opção de baixo desempenho incluem:
- muitos inquilinos com poucos dados cada
- abordagem sem estado para conexões em que cada solicitação pode ser qualquer locatário
- biblioteca cliente ou orm que armazena em cache metadados para todas as tabelas (como ActiveRecord)
- um requisito para armazenamento em cache e/ou pool de conexões eficiente e de alto desempenho
- problemas com VACUUM e outras operações administrativas do PostgreSQL que escalonam mal em milhares de tabelas.
Se o esquema de locatário é ruim para migrações/alterações de esquema realmente depende de como você as está fazendo. É ruim para implantar uma alteração de esquema universal rapidamente, mas é bom para implantar alterações de esquema como uma distribuição gradual entre locatários.
tabela compartilhada funciona melhor para situações em que você tem muitos inquilinos e muitos de seus inquilinos têm muito poucos dados. Um exemplo disso seria um aplicativo móvel de mídia social que permite contas gratuitas e, portanto, tem milhares de contas abandonadas. Outras coisas que tornam o modelo de tabela compartilhada benéfico são:
- melhor para o pool de conexões, pois todas as conexões podem usar o mesmo pool
- melhor para administração do PostgreSQL, devido ao número total de menos tabelas
- melhor para migrações e alterações de esquema, pois há apenas um "conjunto" de tabelas
A principal desvantagem da tabela compartilhada é a necessidade de anexar a condição de filtro de locatário em cada consulta na camada de aplicativo. Também é problemático porque:
- consultas que unem muitas tabelas podem ter um desempenho ruim porque o filtro de locatário atrapalha o planejamento da consulta
- tabelas que crescem para 100 milhões de linhas podem causar problemas específicos de desempenho e manutenção
- não há como fazer alterações de aplicativo específicas do locatário ou atualizações de esquema
- mais caro migrar locatários entre servidores
Portanto, qual modelo "desempenha melhor" realmente depende de quais compensações o prejudicam mais.
Há também um modelo híbrido, "tenant-view", onde os dados reais são armazenados em tabelas compartilhadas, mas cada conexão de aplicativo usa visualizações de barreira de segurança para visualizar os dados. Isso tem algumas das vantagens de cada modelo. Principalmente, ele tem os benefícios de segurança do modelo de esquema de locatário com algumas das desvantagens de desempenho de ambos os modelos.