banco de dados de duas colunas lógico OU índice, ou criar separado 'index' tabela
-
13-12-2019 - |
Pergunta
Eu tenho essa tabela a seguir:
Matches -> match_id, team_a_id , team_b_id, score
Esta tabela irá gravar os jogos entre duas equipes (equipe A e equipe B).No entanto, às vezes, A equipa A jogar como o anfitrião e, por vezes, da equipa B joga como o anfitrião.Portanto, quando eu tentei encontrar o histórico de partidas entre equipa a e da equipa b.O que eu atualmente estou fazendo o que é para
select * from matches where (team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1);
Existe alguma melhor aproximação para o caso?Como para a consulta acima, estou certo de incluir o índice de combinação team_a_id e team_b_id?Mas mesmo assim, então eu ainda tenho um Lógico OU condição entre AB OU BA.
Como alternativa, Eu tenho uma outra idéia, que é ter de outra tabela, vamos dizer que a história
History -> team_hash, match_id
Eu manualmente construir team_hash onde hash(a,b) == hash(b,a)
.Mas este resultado ligeiramente mais lento insira mas a leitura mais rápida.Ou é realmente a leitura mais rápida?
Solução
Assumindo que há um índice composto em {team_a_id, team_b_id}
, o DBMS pode executar a instrução de SQL usando apenas duas índice de procura (uma para o team_a_id = 1 and team_b_id = 2
e o outro para o team_a_id = 2 and team_b_id = 1
), que é muito rápido.Eu não espero que você deve achar que o desempenho deficiente.
No entanto, há uma maneira de eliminar um desses índice de procura.Adicionar uma restrição de...
CHECK(team_a_id < team_b_id)
...e codificar uma "direção" (i.é.qual a equipa que é host) em um campo separado, se necessário.Dessa forma, você sabe team_a_id = 2 and team_b_id = 1
nunca pode ser verdade, então você só precisa de pesquisa em team_a_id = 1 and team_b_id = 2
.
"Simétrico" hash é uma idéia legal, mas:
- A correção do hash não pode ser imposta de forma declarativa - você precisará fazê-lo através de um trigger ou no nível do aplicativo.
- É um redundante de dados.Você vai precisar para manter
team_a_id
eteam_b_id
de qualquer maneira para resolver hash conflitos.Maiores dados com eficiência significa menor cache. - Ele pode realmente aumentar o número de índices - a aplicação eficaz da integridade referencial provavelmente exigirá índices
team_a_id
eteam_b_id
mesmo se você não precisar deles para o real consulta SQL.Além de colocar mais pressão no cache, cada índice adicional deve ser mantida, potencialmente prejudicando a INSERÇÃO/ATUALIZAÇÃO/EXCLUSÃO de desempenho.A situação é especialmente grave em InooDB onde você não pode desativar o agrupamento, assim, índices secundários tendem a ser mais caros do que na pilha baseado em tabelas (consulte o "Desvantagens de cluster" em este artigo).
Outras dicas
Você também pode fazer a sua cláusula WHERE algo como isto
((team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1))
AND team_a_id IN (1,2) AND team_b_id IN (1,2)
desta forma, será possível a utilização de um índice como (team_a_id,team_b_id).