Versão curta
Eu tenho que adicionar um número fixo de propriedades adicionais a cada par em uma associação muitos-para-muitos existente. Passando para os diagramas abaixo, qual das Opções 1-4 é a melhor maneira, em termos de vantagens e desvantagens, de conseguir isso estendendo o Caso Base? Ou existe uma alternativa melhor que eu não considerei aqui?
Versão mais longa
Atualmente, tenho duas tabelas em um relacionamento muitos para muitos, por meio de uma tabela de junção intermediária. Agora preciso adicionar links adicionais às propriedades que pertencem ao par de objetos existentes. Eu tenho um número fixo dessas propriedades para cada par, embora uma entrada na tabela de propriedades possa ser aplicada a vários pares (ou mesmo ser usada várias vezes para um par). Estou tentando determinar a melhor maneira de fazer isso e estou tendo problemas para resolver como pensar na situação. Semanticamente, parece que posso descrevê-lo como um dos seguintes igualmente bem:
- Um par vinculado a um conjunto de um número fixo de propriedades adicionais
- Um par vinculado a muitas propriedades adicionais
- Muitos (dois) objetos vinculados a um conjunto de propriedades
- Muitos objetos vinculados a muitas propriedades
Exemplo
Eu tenho dois tipos de objetos, X e Y, cada um com IDs exclusivos, e uma tabela de vínculo objx_objy
com colunas x_id
e y_id
, que juntos formam a chave primária do link. Cada X pode estar relacionado a muitos Ys e vice-versa. Essa é a configuração do meu relacionamento muitos-para-muitos.
Caso base
Agora, adicionalmente, tenho um conjunto de propriedades definidas em outra tabela e um conjunto de condições sob as quais um determinado par (X, Y) deve ter a propriedade P. O número de condições é fixo e o mesmo para todos os pares. Eles basicamente dizem "Na situação C1, o par (X1, Y1) possui a propriedade P1", "Na situação C2, o par (X1, Y1) possui a propriedade P2" e assim por diante, para três situações / condições para cada par na junção mesa.
Opção 1
Na minha situação atual há exatamente três tais condições, e eu não tenho nenhuma razão para esperar que a aumentar, então uma possibilidade é adicionar colunas c1_p_id
, c2_p_id
e c3_p_id
para featx_featy
, especificando para um determinado x_id
e y_id
, que a propriedade p_id
para uso em cada um dos três casos .
Isso não parece uma ótima idéia para mim, porque complica o SQL para selecionar todas as propriedades aplicadas a um recurso e não é facilmente escalável para mais condições. No entanto, ele impõe a exigência de um certo número de condições por par (X, Y). De fato, é a única opção aqui que faz isso.
opção 2
Crie uma tabela de condições cond
e adicione o ID da condição à chave primária da tabela de junção.
Uma desvantagem disso é que ele não especifica o número de condições para cada par. Outra é que, quando estou apenas considerando o relacionamento inicial, com algo como
SELECT objx.*, objy.* FROM objx
INNER JOIN objx_objy ON objx_objy.x_id = objx.id
INNER JOIN objy ON objy.id = objx_objy.y_id
Em seguida, tenho que adicionar uma DISTINCT
cláusula para evitar entradas duplicadas. Isso parece ter perdido o fato de que cada par deveria existir apenas uma vez.
Opção 3
Crie um novo 'ID do par' na tabela de junção e, em seguida, tenha uma segunda tabela de links entre a primeira e as propriedades e condições.
Isso parece ter o menor número de desvantagens, exceto a falta de impor um número fixo de condições para cada par. No entanto, faz sentido criar um novo ID que não identifique nada além dos existentes?
Opção 4 (3b)
Basicamente, o mesmo que a Opção 3, mas sem a criação do campo ID adicional. Isso é feito colocando os dois IDs originais na nova tabela de junção, para que ele contenha x_id
e y_id
campos, em vez de xy_id
.
Uma vantagem adicional desse formulário é que ele não altera as tabelas existentes (embora elas ainda não estejam em produção). No entanto, basicamente duplica uma tabela inteira várias vezes (ou parece que é assim mesmo) e também não parece ideal.
Sumário
Meu sentimento é que as opções 3 e 4 são semelhantes o suficiente para que eu pudesse ir com qualquer uma delas. Eu provavelmente teria agora, se não fosse a exigência de um número pequeno e fixo de links para propriedades, o que faz a Opção 1 parecer mais razoável do que seria. Com base em alguns testes muito limitados, a adição de uma DISTINCT
cláusula às minhas consultas não parece afetar o desempenho nessa situação, mas não tenho certeza de que a Opção 2 represente a situação e as demais, devido à duplicação inerente causada pela colocação os mesmos pares (X, Y) em várias linhas da tabela de links.
É uma dessas opções o meu melhor caminho a seguir ou há outra estrutura que devo considerar?
fonte
DISTINCT
cláusula, eu estava pensando em uma consulta como a que está no final do nº 2, que vinculax
ey
através,xyc
mas não se refere ac
... Então, se eu tiver(x_id, y_id, c_id)
restriçõesUNIQUE
com linhas(1,1,1)
e(1,1,2)
, entãoSELECT x.id, y.id FROM x JOIN xyc JOIN y
, retornarei duas idênticas linhas(1,1)
, e(1,1)
.Respostas:
Opção 1
Isso não complica necessariamente a consulta SQL (veja a conclusão abaixo).
É facilmente escalável para mais condições, desde que ainda haja um número fixo de condições e não haja dezenas ou centenas.
É verdade, e embora você diga em um comentário que isso é "o menos importante dos meus requisitos", você não disse que isso não importa.
opção 2Eu acho que você pode descartar essa opção por causa das complicações mencionadas. A
objx_objy
mesa é provável que seja a tabela de condução para algumas das suas consultas (por exemplo, "selecionar todas as propriedades aplicadas a um recurso", que estou tomando para dizer todas as propriedades aplicadas a umaobjx
ouobjy
). Você pode usar uma visualização para pré-aplicar aDISTINCT
consulta, para que não seja uma questão de complicar as consultas, mas isso será muito ruim em termos de desempenho para obter muito pouco ganho.Opção 3Não, não - a opção 4 é melhor em todos os aspectos.
Opção 4
Essa opção é ótima - é a maneira óbvia de configurar as relações se o número de propriedades for variável ou sujeito a alterações
Conclusão
Minha preferência seria a opção 1 se o número de propriedades por
objx_objy
provavelmente for estável, e se você não puder imaginar adicionar mais do que um punhado extra. Também é a única opção que impõe a restrição 'número de propriedades = 3' - impor uma restrição semelhante na opção 4 provavelmente envolveria a adição dec1_p_id
... colunas à tabela xy de qualquer maneira *.Se você realmente não se importa muito com essa condição, e também tem motivos para duvidar que o número de condições da propriedade seja estável, escolha a opção 4.
Se você não tiver certeza de qual, escolha a opção 1 - é mais simples e definitivamente melhor se você tiver a opção, como outros já disseram. Se você deixar a opção 1 "... porque complicar o SQL para selecionar todas as propriedades aplicadas a um recurso ...", sugiro a criação de uma exibição para fornecer os mesmos dados que a tabela extra na opção 4:
tabelas da opção 1:
vista para 'emular' opção 4:
"selecione todas as propriedades aplicadas a um recurso":
dbfiddle aqui
fonte
Acredito que qualquer uma dessas opções poderia funcionar, mas eu iria com a opção 1 se o número de condições for realmente fixado em 3 e a opção 2, se não for. O aparelho de barbear da Occam também funciona para o design de banco de dados, todos os outros fatores sendo iguais ao design mais simples geralmente são os melhores.
Embora se você deseja seguir regras rígidas de normalização do banco de dados, acredito que você precisaria usar 2, independentemente de o número de condições ser fixo.
fonte