Se A
for um amigo de B
, devo armazenar os dois valores AB
e BA
, ou um é suficiente? Quais são as vantagens e desvantagens de ambos os métodos.
Segue minha observação:
- Se eu mantiver os dois, terei que atualizar ambos quando receber uma solicitação de um amigo.
- Se eu não mantiver os dois, achei difícil ter que fazer vários
JOIN
com essa tabela.
Atualmente, mantenho o relacionamento de um jeito.
Então o que devo fazer neste caso? Algum conselho?
Eu armazenaria AB e BA. Uma amizade é realmente uma relação de mão dupla, cada entidade está ligada a outra. Embora intuitivamente pensemos na "amizade" como um elo entre duas pessoas, do ponto de vista relacional é mais como "A tem um amigo B" e "B tem um amigo A". Dois relacionamentos, dois registros.
Se a amizade pretende ser simétrica (ou seja, não é possível
A
ser amigo,B
mas não vice-versa), então eu apenas armazenaria o relacionamento unidirecional com uma restrição de verificação, garantindo que cada relacionamento só possa ser representado de uma maneira.Além disso, eu abandonaria o id substituto e teria um PK composto (e possivelmente um índice exclusivo composto também nas colunas invertidas).
Você não diz as consultas que isso dificulta, mas sempre pode criar uma View
Assumindo que uma "amizade" é sempre de mão dupla/mútua, eu provavelmente lidaria com algo assim.
O resultado é que você muda de uma junção muitos para muitos de "pessoa" para "pessoa", para uma junção muitos para muitos de "pessoa" para "amizade". Isso simplificará junções e restrições, mas tem o efeito colateral de permitir mais de duas pessoas em uma única "amizade" (embora talvez a flexibilidade adicional seja uma vantagem potencial).
Você pode precisar definir índices em torno de amizades em vez de dobrar o número de linhas:
Dessa forma, você dobra o armazenamento para índices, mas não para os dados da tabela. Como resultado, isso deve representar uma economia de 25% no espaço em disco. O MySQL Query Optimizer escolherá executar apenas varreduras de intervalo de índice, e é por isso que o conceito de cobertura de índices funciona bem aqui.
Aqui estão alguns links interessantes sobre Índices de Cobertura:
EMBARGO
Se a amizade não é mútua, você tem a base para outro tipo de relacionamento : SEGUIDOR
Se friend_to não for amigo de friend_of, você pode simplesmente deixar esse relacionamento fora da mesa.
Se você quiser definir relacionamentos para todos os tipos, sejam eles mútuos ou não, provavelmente poderá usar o seguinte layout de tabela:
Na tabela de relações, você pode organizar as relações para incluir o seguinte:
Isso deve ser mais robusto para todos os relacionamentos, sejam eles mútuos ou não.
Se você pode controlar dentro do aplicativo que o id de A é sempre menor que o id de B (pré-encomendar os ids dos elementos A,B) você pode aproveitar de pedir sem um OR (selecione onde id_A = a AND id_B = b, em vez de perguntar (id_A = a AND id_B = b) OR (id_A = b AND id_B = a) ), e também manter metade dos registros necessários com as outras aproximações. Em seguida, você deve usar outro campo para manter o estado do relacionamento ( are-friends, a-solicited-to-b, b-solicited-to-a, exfriends-a, exfriends-b ), e pronto.
Esta é a maneira que eu gerenciei meu sistema de amizade, e isso simplifica o sistema e usa metade das linhas que você precisa com outros sistemas, apenas dizendo que A é igual ao valor de id mais baixo no código.