Por que não deveria ter uma tabela para vários relacionamentos?

12

Supondo que eu tenha várias relações no meu banco de dados, por exemplo, Loja, Funcionário e Venda, e desejo conectar pares a um relacionamento binário simples. Pessoalmente, eu criaria tabelas denominadas Employee_Store e Employee_Sale com uma chave natural composta pelas chaves estrangeiras.

Agora, meu colega insiste em criar uma tabela para vários relacionamentos. Para o exemplo acima, pode haver uma tabela chamada EmployeeLinks:

EmployeeLinks(
    IdLink int PK, 
    IdEmployee int FK null,
    IdStore int FK null,
    IdSale int FK null,
    LinkType int not null
)

Por favor, ajude-me com boas razões pelas quais essa não é uma boa ideia. Tenho meus próprios argumentos, mas gostaria de mantê-los em sigilo e ouvir suas opiniões imparciais.

EDITAR:

Inicialmente, a tabela acima não teria chave primária (!). Como as chaves estrangeiras permitem nulo, uma chave substituta é a única opção.

Tomasz Pluskiewicz
fonte
3
É como OTLT ou EAV, mas pior porque prolifera colunas em vez de linhas!
onedaywhen

Respostas:

13

O que seu colega propõe como chave primária para esta tabela de links?
As colunas da chave primária não podem ser NULL, é claro: a tabela acima pode ser anulada.

Não há nenhum identificador de linha natural (que é o que é uma PK) no exemplo acima (uma coluna IDENTITY não é uma chave primária); portanto, ela falha em qualquer processo de modelagem. Nem pense em criar tabelas sem algum modelo (ERD, ORM, IDEF1X, qualquer que seja)

Você também precisaria de restrições CHECK para garantir que não tenha links de três vias.

Finalmente, você está entrando no 4º e 5º território de forma normal, mas pelas razões erradas.

Não consigo encontrar nenhum exemplo na internet: isso mostra como isso é estúpido.

gbn
fonte
4
+1 paraI can't find any examples on the internet: that shows how stupid this is
JNK
Eu deixei mais claro a chave primária. Além disso, aparentemente, meu colega já se deparou com esse projeto antes ou assim me disseram
Tomasz Pluskiewicz
@Tomasz Pluskiewicz: Uma chave substituta não é a chave primária! É escolhido para complementar a chave natural no momento da implementação. Consulte dba.stackexchange.com/a/13779/630 Além disso, seu colega deve nos mostrar um artigo oficial que demonstra essa técnica. Eu já vi pilhas completas de lixo no meu tempo, mas não as repito ...
gbn
12

A primeira razão prática em que consigo pensar é no desempenho.

Em um modelo "tradicional", você pode ter um índice exclusivo Idemployee, Idstoreou quaisquer que sejam os campos e obter um ótimo desempenho nas pesquisas. Também é fácil de manter para inserções. Índices exclusivos permitem que você junte junções com mais frequência, o que pode tornar muitos JOINs incrivelmente rápidos.

No seu modelo de exemplo, para obter um desempenho decente, você precisará ter um índice de campo único em cada campo FK da tabela, no mínimo, idealmente um índice de cobertura para todas as combinações que serão referenciadas, ou seja:

  • Funcionário / Loja
  • Empregado / Venda

Não sei o que é o tipo de link, mas se você o referenciar, provavelmente deve ser indexado.

Esses índices precisarão ser mantidos para todas as linhas da tabela, independentemente de o campo estar preenchido ou não. Você pode adicionar um filtro, mas isso também será complicado com tantas combinações.

Isso também complicará sua lógica. Você precisará fazer uma pesquisa na identificação do funcionário, encontrar uma linha com um valor de loja vazio e atualizar; ou apenas insira uma nova linha para cada novo link, o que meio que anula o objetivo de consolidar os campos.

Basicamente, você estará usando MAIS espaço em disco, tendo mais índices para manter e complicando sua lógica por praticamente nenhuma razão. O único "benefício" é que há menos tabelas para lidar.

JNK
fonte
A coluna LinkType é um tipo de discriminador. Apenas dizendo qual par uma linha realmente se relaciona. Apenas aumenta a engenhoca se você me perguntar.
Tomasz Pluskiewicz
@TomaszPluskiewicz Acho que a melhor maneira de mostrar a ele por que é péssimo é criar um conjunto de dados de amostra com os dois tipos de tabelas e executar algumas consultas. Seu modelo será muito mais lento do que um modelo tradicional
JNK
4

Colocar vários relacionamentos em uma tabela pode ser útil se esses relacionamentos tiverem os mesmos atributos e / ou se você desejar agregar dados em vários relacionamentos.

É necessário se os tipos de relacionamentos forem definidos pelo usuário em tempo de execução. No entanto, isso raramente é realmente o caso.

No seu exemplo, os relacionamentos não compartilham atributos, os relacionamentos até referem duas tabelas diferentes. Isso dificulta a aplicação de restrições e o design também é menos intuitivo.

Eu escolheria esse design apenas se a criação de tabelas custasse literalmente dinheiro.

JMD Coalesce
fonte