Existem várias razões pelas quais o uso de uma grande "mesa divina" é ruim. Vou tentar ilustrar os problemas com um banco de dados de exemplo inventado. Vamos supor que você esteja tentando modelar eventos esportivos. Diremos que você deseja modelar jogos e as equipes que jogam nesses jogos. Um design com várias tabelas pode se parecer com isso (isso é muito simplista de propósito, portanto, não seja pego em locais onde mais normalização possa ser aplicada):
Teams
Id | Name | HomeCity
Games
Id | StartsAt | HomeTeamId | AwayTeamId | Location
e um banco de dados de tabela única ficaria assim
TeamsAndGames
Id | TeamName | TeamHomeCity | GameStartsAt | GameHomeTeamId | GameAwayTeamId | Location
Primeiro, vejamos como criar índices nessas tabelas. Se eu precisasse de um índice na cidade natal para uma equipe, poderia adicioná-lo à Teams
mesa ou à TeamsAndGames
mesa com bastante facilidade. Lembre-se de que sempre que você cria um índice, ele precisa ser armazenado no disco em algum lugar e atualizado à medida que as linhas são adicionadas à tabela. No caso da Teams
tabela, isso é bastante direto. Coloquei uma nova equipe, o banco de dados atualiza o índice. Mas e para TeamsAndGames
quê? Bem, o mesmo se aplica a partir doTeams
exemplo. Eu adiciono uma equipe, o índice é atualizado. Mas também acontece quando adiciono um jogo! Mesmo que esse campo seja nulo para um jogo, o índice ainda precisa ser atualizado e armazenado em disco para esse jogo. Para um índice, isso não parece muito ruim. Mas quando você precisa de muitos índices para as várias entidades amontoadas nesta tabela, você perde muito espaço armazenando os índices e muito tempo do processador atualizando-os para itens onde eles não se aplicam.
Segundo, consistência dos dados. No caso de usar duas mesas separadas, posso usar chaves estrangeiras Games
da Teams
mesa para definir quais times estão jogando em um jogo. E, assumindo que as colunas HomeTeamId
e AwayTeamId
não são anuláveis, o banco de dados garantirá que todos os jogos que eu participe tenham 2 equipes e que essas equipes existam no meu banco de dados. Mas e o cenário de tabela única? Bem, como existem várias entidades nesta tabela, essas colunas devem ser anuláveis (você pode torná-las não anuláveis e colocar dados de lixo nela, mas isso é apenas uma ideia horrível). Se essas colunas forem anuláveis, o banco de dados não poderá mais garantir que, quando você insere um jogo, ele possui duas equipes.
Mas e se você decidir fazer isso de qualquer maneira? Você configura as chaves estrangeiras de modo que esses campos aponte para outra entidade na mesma tabela. Mas agora o banco de dados apenas garantirá que essas entidades existam na tabela, não que sejam do tipo correto. Você pode facilmente definir GameHomeTeamId
o ID de outro jogo e o banco de dados não irá reclamar. Se você tentasse isso no cenário de várias tabelas, o banco de dados seria adequado.
Você pode tentar mitigar esses problemas dizendo "bem, apenas garantiremos que nunca façamos isso no código". Se você está confiante em sua capacidade de escrever código sem erros pela primeira vez e em levar em conta todas as combinações estranhas de coisas que um usuário pode tentar, vá em frente. Pessoalmente, não estou confiante em minha capacidade de fazer uma dessas coisas, por isso deixarei o banco de dados fornecer uma rede de segurança extra.
(Isso fica ainda pior se seu design é aquele em que você copia todos os dados relevantes entre linhas em vez de usar chaves estrangeiras. Qualquer inconsistência ortográfica / de outros dados será difícil de resolver. Como você pode saber se "Jon" é um erro de ortografia de "John "ou se foi intencional (porque são duas pessoas separadas)?)
Terceiro, quase todas as colunas precisam ser anuláveis ou devem ser preenchidas com dados copiados ou com lixo. Um jogo não precisa de um TeamName
ou TeamHomeCity
. Portanto, todo jogo precisa de algum tipo de espaço reservado ou precisa ser anulável. E se for anulável, o banco de dados terá prazer em jogar sem TeamName
. Também será necessária uma equipe sem nome, mesmo que sua lógica de negócios diga que isso nunca deve acontecer.
Existem várias outras razões pelas quais você deseja tabelas separadas (incluindo a preservação da sanidade do desenvolvedor). Existem até algumas razões pelas quais uma tabela maior pode ser melhor (a desnormalização às vezes melhora o desempenho). Esses cenários são poucos e distantes entre si (e geralmente são mais bem tratados quando você tem métricas de desempenho para mostrar que esse é realmente o problema, não um índice ausente ou algo mais).
Por fim, desenvolva algo que seja fácil de manter. Só porque "funciona" não significa que está tudo bem. Tentar manter tabelas de deus (como classes de deus) é um pesadelo. Você está se preparando para a dor mais tarde.