Existem várias razões pelas quais usar uma grande "tabela de deus" é ruim. Vou tentar ilustrar os problemas com um banco de dados de exemplo inventado. Vamos supor que você esteja tentando modelar eventos esportivos. Nós diremos que você quer 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 lugares 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, vamos analisar índices nessas tabelas. Se eu precisasse de um índice na cidade de origem para um time, eu poderia adicioná-lo facilmente à tabela Teams
ou à tabela TeamsAndGames
. Lembre-se de que, sempre que você criar um índice, ele precisa ser armazenado em algum lugar no disco e atualizado conforme as linhas são adicionadas à tabela. No caso da tabela Teams
, isso é bastante simples. Eu coloquei uma nova equipe, o banco de dados atualiza o índice. Mas e quanto a TeamsAndGames
? Bem, o mesmo se aplica a partir do exemplo Teams
. Eu adiciono uma equipe, o índice é atualizado. Mas também acontece quando eu adiciono um jogo! Mesmo que esse campo seja nulo para um jogo, o índice ainda precisa ser atualizado e armazenado no disco para esse jogo. Para um índice, isso não parece muito ruim. Mas quando você precisa de muitos índices para as múltiplas entidades amontoadas nesta tabela, você gasta muito espaço armazenando os índices e muito tempo de processador atualizando-os para as coisas em que eles não se aplicam.
Segundo, consistência de dados. No caso de usar duas tabelas separadas, posso usar chaves estrangeiras da tabela Games
para a tabela Teams
para definir quais equipes estão jogando em um jogo. E supondo que eu faça as colunas HomeTeamId
e AwayTeamId
não anuláveis, o banco de dados irá garantir que cada jogo que eu coloquei tenha 2 equipes e que essas equipes existam no meu banco de dados. Mas e o cenário da mesa única? Bem, como há várias entidades nessa tabela, essas colunas devem ser anuláveis (você pode torná-las não anuláveis e inserir dados de lixo lá, mas isso é apenas uma ideia horrível). Se essas colunas forem anuláveis, o banco de dados não poderá mais garantir que, ao inserir um jogo, ele tenha duas equipes.
Mas e se você decidir apenas ir de qualquer maneira? Você configura as chaves estrangeiras de modo que esses campos apontem para outra entidade na mesma tabela. Mas agora o banco de dados apenas fará com que essas entidades existam na tabela, e não que elas sejam do tipo correto. Você pode facilmente definir GameHomeTeamId
para 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 um ajuste.
Você poderia tentar atenuar esses problemas dizendo "bem, só nos certificaremos de que nunca faremos isso no código". Se você está confiante em sua capacidade de escrever código livre de bugs pela primeira vez e em sua capacidade de levar em consideração todas as estranhas combinações de coisas que um usuário pode tentar, vá em frente. Eu pessoalmente não estou confiante em minha capacidade de fazer qualquer uma dessas coisas, então eu vou deixar o banco de dados me dar uma rede de segurança extra.
(Isso fica ainda pior se o design for aquele em que você copie todos os dados relevantes entre as linhas, em vez de usar chaves estrangeiras. Quaisquer inconsistências de ortografia / outros dados serão difíceis de resolver. Como saber se "Jon" é um erro de ortografia? de "John" ou se foi intencional (porque são duas pessoas separadas)?)
Em terceiro lugar, quase todas as colunas precisam ser anuláveis ou devem ser preenchidas com dados copiados ou lixo. Um jogo não precisa de TeamName
ou TeamHomeCity
. Então, qualquer jogo precisa de algum tipo de marcador ou precisa ser anulável. E se for anulável, o banco de dados terá um jogo feliz sem TeamName
. Ele também levará uma equipe sem nome, mesmo que sua lógica de negócios diga que isso nunca deveria acontecer.
Há várias outras razões pelas quais você deseja tabelas separadas (incluindo preservar a sanidade do desenvolvedor). Existem ainda algumas razões pelas quais uma tabela maior pode ser melhor (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 outra coisa qualquer).
Finalmente, 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á apenas se preparando para a dor depois.