Pregunta

Tengo esta siguiente tabla:

Matches -> match_id, team_a_id , team_b_id, score

Esta tabla registrará los partidos entre dos equipos (equipo A y equipo B).Sin embargo, a veces el equipo A juega como anfitrión y otras veces el equipo B juega como anfitrión.Por lo tanto, cuando intenté encontrar coincidencias históricas entre el equipo a y el equipo b.Lo que estoy haciendo actualmente es

select * from matches where (team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1);

¿Existe algún enfoque mejor para tal caso?En cuanto a la consulta anterior, ¿tengo razón al incluir un índice de combinación team_a_id y team_b_id?Pero aun así, todavía tengo una condición OR lógica entre AB O BA.

Alternativamente, Tengo otra idea, que es tener otra mesa digamos historia

History -> team_hash, match_id

Construyo manualmente team_hash donde hash(a,b) == hash(b,a).Pero esto da como resultado una inserción ligeramente más lenta pero una lectura más rápida.¿O es realmente una lectura más rápida?

¿Fue útil?

Solución

Suponiendo que existe un índice compuesto en {team_a_id, team_b_id}, el DBMS puede ejecutar su declaración SQL utilizando sólo dos búsquedas de índice (una para el team_a_id = 1 and team_b_id = 2 y el otro para el team_a_id = 2 and team_b_id = 1), que es muy rápido.No espero que le falte rendimiento.


Sin embargo, existe una manera de eliminar una de estas búsquedas de índice.Añade una restricción...

CHECK(team_a_id < team_b_id)

...y codificar una "dirección" (es decir,qué equipo es el anfitrión) en un campo separado si es necesario.De esta manera ya sabes team_a_id = 2 and team_b_id = 1 nunca puede ser cierto, así que sólo necesitas buscar en team_a_id = 1 and team_b_id = 2.


El hash "simétrico" es una buena idea, pero:

  • La exactitud del hash no se puede imponer de forma declarativa; deberá hacerlo mediante un activador o en el nivel de la aplicación.
  • Es un dato redundante.Tendrás que mantener team_a_id y team_b_id de todos modos para resolver conflictos de hash.Datos más grandes significan efectivamente un caché más pequeño.
  • De hecho, puede aumentar el número de índices; la aplicación eficiente de la integridad referencial probablemente requerirá índices en team_a_id y team_b_id incluso si no los necesita para la consulta SQL real.Además de ejercer más presión sobre el caché, se debe mantener cada índice adicional, lo que podría perjudicar el rendimiento de INSERT/UPDATE/DELETE.La situación es especialmente grave en InooDB, donde no se puede desactivar la agrupación en clústeres, por lo que los índices secundarios tienden a ser más caros que en las tablas basadas en montón (consulte "Desventajas de la agrupación en clústeres" en Este artículo).

Otros consejos

También puedes hacer que tu cláusula WHERE sea algo como esto

((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)

de esta manera será posible utilizar un índice como (team_a_id,team_b_id).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top