Por exemplo, há três tabelas: players
, dungeons
e instances
.
A player
tem muitos dungeons
e cada um dungeon
tem muitos instances
, como em um jogo conhecido de World of Warcraft. Cada player
um teria um dungeon_id
como chave estrangeira e cada dungeon
um teria um instance_id
como chave estrangeira. Essa seria uma abordagem minimalista suficiente. Um player
de cada instance
pode ser acessado através da dungeon
tabela. Isso resultaria em 1 coluna a menos, mas uma consulta um pouco mais longa.
Outra abordagem é adicionar player_id
à instances
tabela como uma chave estrangeira. Agora os jogadores podem consultar diretamente da instances
mesa. Consulta mais curta, mas mais uma coluna para uma chave estrangeira.
Qual abordagem é melhor a longo prazo? Na prática, parece que adicionar uma chave estrangeira em todos os lugares onde é logicamente possível torna mais fácil. Mas então isso não resultaria em um acoplamento mais rígido e tornaria o código mais difícil de refatorar?
IMO, esta será uma abordagem ruim. Esta é uma espécie de referência circular.
Como você tem uma relação de um para muitos, a tabela de mapeamento será separada, masmorra, instância e jogador, cada um terá uma tabela mestre e uma tabela de mapeamento definindo sua relação um para muitos.
se você tiver uma consulta muito frequente entre o jogador e a instância em que não há necessidade de tabela de masmorras na saída e o volume de dados é alto, você pode optar pela desnormalização.
A criação
player_instance mapping table
ou não depende do requisito acima.Mas é desejável alcançar a Desnormalização via
index view
Idealmente , as entidades não devem ter chaves estrangeiras e devem ser consideradas mestres . Assim
player
,dungeon
einstance
são mestres que possuem informações/atributos/campos relacionados às suas próprias características. Você pode ter uma tabela separada para Entidade-Relações . Então você teriaplayer_dungeon
edungeon_instance
(ambos um para muitos conforme o PS). Aqui se você quiser saberinstances
pertencer a umplayer
, você precisa juntar essas duas tabelas.Agora vem o famoso debate: normalização vs desnormalização. A primeira abordagem é pelo livro e funcionaria. Mas é difícil dimensionar à medida que as tabelas crescem (apesar de ter índices adequados). Então você tenta desnormalizar a solução acima dependendo do volume de consultas que estão acontecendo nessas tabelas.
Como você especificou uma consulta aqui, estou assumindo que é uma consulta frequente (gargalo). Se houver muitas consultas desse tipo, você pode ter outra tabela de relacionamentos
player_instance
. Agora resolvemos o problema da latência, mas demos origem a um problema maior:Consistência : Agora existem duas maneiras de encontrar a
instances
pertença a um arquivoplayer
. Uma é diretamente porplayer_instance
tabela, outra por junçãoplayer_dungeon
edungeon_instance
. Devemos sempre obter a mesma resposta dessas duas abordagens. Para garantir que agora precisamos fazer nossas gravações sofrerem. Como?player_dungeon
mesa, também precisamos inserir naplayer_instance
tabela (para a qual temos que consultardungeon_instance
para ver todas essas instâncias mapeadas para essa masmorra em particular).dungeon_instance
, precisamos mapear todos os jogadores existentes para essa instância que mapeamos para essa masmorra em particular. Não soa bem, não é?Ainda não terminamos. Todas essas operações devem ser atômicas (ou seja, em uma transação) ou então haverá inconsistência por um curto período de tempo.
Finalmente, precisamos fazer uma troca. Você quer tornar as leituras do seu banco de dados lentas ou as gravações sofrerem? Você precisa tornar seu sistema responsivo/disponível ou consistente? A decisão é sua.
Por favor, leia o teorema CAP para detalhes.