Estaba ejecutando una consulta de este tipo de consulta:
SELECT -- fields FROM table1 JOIN table2 ON (table1.c1 = table.c1 OR table1.c2 = table2.c2) WHERE -- conditions Pero el OR lo hizo muy lento, así que lo dividí en 2 consultas:
SELECT -- fields FROM table1 JOIN table2 ON table1.c1 = table.c1 WHERE -- conditions UNION SELECT -- fields FROM table1 JOIN table2 ON table1.c2 = table.c2 WHERE -- conditionsLo cual funciona mucho mejor, pero ahora estoy revisando las tablas dos veces, así que me preguntaba si había más optimizaciones, por ejemplo, obtener un conjunto de entradas que satisfaga la condición (tabla1.c1 = tabla.c1 O tabla1.c2 = tabla2.c2) y luego consultarlo. Eso me llevaría de vuelta a lo primero que estaba haciendo, pero tal vez haya otra solución que no tengo en mente. Entonces, ¿hay algo más que hacer con eso o ya es óptimo?
Dividir la consulta en dos separadas suele ser mejor en MySQL, ya que rara vez utiliza la operación "Índice OR" ( Fusión de índice en la jerga de MySQL).
Hay algunos elementos en los que me concentraría para una mayor optimización, todos relacionados con la indexación:
1. Filtra las filas más rápido
El predicado en la cláusula WHERE debe optimizarse para recuperar la menor cantidad de filas. Y deben analizarse en términos de selectividad para crear índices que puedan producir los datos con el menor filtrado posible (menos lecturas).
2. Acceso para unirse
La recuperación de filas relacionadas también debe optimizarse. De acuerdo con la selectividad, debe decidir qué tabla es más selectiva y usarla como tabla de control, y considerar la otra como tabla de bucle anidado. Ahora, para este último, debe crear un índice que recupere las filas de manera óptima.
3. Índices de cobertura
Por último, pero no menos importante, si su consulta aún es lenta, hay una cosa más que puede hacer: usar índices de cobertura. Es decir, expanda sus índices para incluir todas las filas de las tablas de control y/o secundarias en ellos. De esta forma el motor InnoDB no necesitará leer dos índices por tabla, sino uno solo.
Prueba
SELECT -- fields FROM table1 JOIN table2 ON table1.c1 = table2.c1 WHERE -- conditions UNION ALL SELECT -- fields FROM table1 JOIN table2 ON table1.c2 = table2.c2 WHERE -- conditions /* add one more condition which eliminates the rows selected by 1st subquery */ AND table1.c1 != table2.c1Copiado de los comentarios:
Nico Haase > ¿Qué quieres decir con "prueba"?
OP muestra solo patrones de consulta. Por lo tanto, no puedo predecir si la técnica es efectiva o no, y sugiero que OP pruebe mi variante en su estructura y matriz de datos.
Nico Haase > lo que has cambiado
He agregado una condición más a la segunda subconsulta: vea el comentario agregado en el código.
Nico Haase > ¿y por qué?
Esto reemplaza UNION DISTINCT con UNION ALL y elimina la ordenación combinada de conjuntos de filas para la eliminación de duplicados.