Estou desenvolvendo uma relação de amizade no MySQL, onde a relação de amizade é mútua. Se A é amigo de B, B é amigo de A. Se um dos usuários termina a amizade, a relação cai. Eu quero aprender qual caminho é melhor.
Eu tenho um sistema em execução;
user
-----------
userid p.k
name
friends
-------
userid
friendid
primary key (`userid`,`friendid`),
key `friendid` (`friendid`)
1 2
2 5
1 3
To get all of my friends;
SELECT u.name, f.friendid , IF(f.userid = $userid, f.friendid, f.userid) friendid
FROM friends f
inner join user u ON ( u.userid = IF(f.userid = $userid, f.friendid, f.userid))
WHERE ( f.userid = '$userid' or f.friendid = '$userid' )
Esta consulta funciona bem. Talvez eu possa adicionar um UNION
. A consulta é mais complicada que a abaixo e a tabela contém metade do número de registros que a abaixo.
Outra maneira é manter as relações em linhas separadas;
1 2
2 1
2 5
5 2
1 3
3 1
SELECT u.name, f.friendid
FROM friends f inner join user u ON ( u.userid = f.friendid )
WHERE f.userid = '$userid'
Essa consulta é simples, embora a tabela ocupe o dobro do espaço.
Minha preocupação é; assumindo que existem milhões de usuários; para que lado funcionará mais rápido?
Quais são as vantagens e desvantagens de ambas as maneiras?
O que devo ter em mente ou mudar para essas maneiras? E que problemas posso enfrentar pelos dois lados?
fonte
Respostas:
A primeira coisa que chama minha atenção é a configuração do índice
friends
.Você tem isso no momento:
Ao procurar por amizade mútua, isso pode resultar em uma pequena despesa, pois o ID do usuário pode ser recuperado da tabela ao percorrer o
friendid
índice. Talvez você possa indexar da seguinte maneira:Isso pode remover qualquer necessidade de acessar a tabela e pesquisar apenas o índice.
Agora, em termos de consultas, as duas podem melhorar com o novo índice exclusivo. Criando o índice exclusivo também elimina a necessidade de inserir
(A,B)
e(B,A)
na tabela porque(A,B)
e(B,A)
seria o índice de qualquer forma. Portanto, a segunda consulta não precisaria examinar a tabela para ver se alguém é amigo de outra pessoa porque outra pessoa iniciou a amizade. Dessa forma, se a amizade é quebrada por apenas uma pessoa, não há amizades órfãs unilaterais (parece muito com a vida hoje em dia, não é?)Sua primeira consulta parece se beneficiar mais do índice exclusivo. Mesmo com milhões de linhas, localizar amigos usando apenas os índices evitaria tocar na tabela. Ainda assim, como você não apresentou uma consulta UNION, eu gostaria de recomendar uma consulta UNION:
Isso permitirá que você veja quem são os amigos de cada ID de usuário
Para ver todas as amizades, execute o seguinte:
Primeiro, aqui estão alguns dados de amostra:
Vamos olhar para todos os relacionamentos
Vamos examinar todos os 5 IDs de usuário e ver se os relacionamentos são mostrados corretamente
Todos eles parecem corretos para mim.
Agora, vamos usar sua segunda consulta para ver se ela corresponde ...
Por que não combinar? Isso porque eu não carreguei o
(B,A)
para todos(A,B)
. Deixe-me carregar os(B,A)
relacionamentos e tente sua segunda consulta novamente.Eles ainda não combinam. Isso ocorre porque sua segunda consulta está apenas verificando um lado.
Vamos verificar sua primeira consulta em todos os valores com apenas (A, B) e não (B, A):
Seu primeiro funciona bem. Estou certo de que ele está se beneficiando do índice único, como disse anteriormente, mas IMHO acho que a UNIÃO é mais simples. Com esse índice único, pareceria ser seis de uma e meia dúzia do outro em termos de execução e saída.
Você teria que comparar sua primeira consulta com a minha sugestão UNION e ver.
Esta foi uma boa pergunta que você fez hoje. +1 para sua pergunta.
fonte
friendid
,userid
) e agora os resultados são cerca de .00794 É o mais rápido possível? Olhando para os resultados, você acha que a primeira maneira é melhor (uma linha para cada relação)? Porque é duas vezes menos espaço que o segundo e os resultados são praticamente os mesmos nas configurações atuais.WHERE
,GROUP BY
eORDER BY
cláusulas resultar em dados sendo lidos apenas índices. Aqui estão alguns bons links que justificam o uso das chaves exclusivas e primárias como índices de cobertura: 1) peter-zaitsev.livejournal.com/6949.html , 2) mysqlperformanceblog.com/2006/11/23/… , 3) ronaldbradford .com / blog / tag / cover-index