usa tutorial sobre que para instalar index funciona elastic crear como comandos mysql performance sql-execution-plan

mysql - tutorial - todo sobre elasticsearch



¿Hay alguna forma de forzar el orden de ejecución de MySQL? (3)

Sé que puedo cambiar la forma en que MySQL ejecuta una consulta utilizando la palabra clave FORCE INDEX (abc) . ¿Pero hay una manera de cambiar el orden de ejecución?

Mi consulta se ve así:

SELECT c.* FROM table1 a INNER JOIN table2 b ON a.id = b.table1_id INNER JOIN table3 c ON b.itemid = c.itemid WHERE a.itemtype = 1 AND a.busy = 1 AND b.something = 0 AND b.acolumn = 2 AND c.itemid = 123456

Tengo una clave para cada relación / restricción que uso. Si ejecuto la explicación en esta declaración, veo que mysql comienza a consultar c primero.

id select_type table type 1 SIMPLE c ref 2 SIMPLE b ref 3 SIMPLE a eq_ref

Sin embargo, sé que consultar en el orden a -> b -> c sería más rápido (lo he probado) ¿Hay alguna forma de decirle a mysql que use un orden específico?

Actualización: así es como sé que a -> b -> c es más rápido.

La consulta anterior tarda 1.9 segundos en completarse y devuelve 7 filas. Si cambio la consulta a

SELECT c.* FROM table1 a INNER JOIN table2 b ON a.id = b.table1_id INNER JOIN table3 c ON b.itemid = c.itemid WHERE a.itemtype = 1 AND a.busy = 1 AND b.something = 0 AND b.acolumn = 2 HAVING c.itemid = 123456

la consulta se completa en 0.01 segundos (sin usar, obtengo 10.000 filas). Sin embargo, esa no es una solución elegante porque esta consulta es un ejemplo simplificado. En el mundo real me he unido de c a otras tablas. Dado que HAVING es un filtro que se ejecuta en todo el resultado, esto significaría que obtendría algunos registros de magnitudes más db que nescessary.

Edit2: Sólo un poco de información:

  • La parte variable en esta consulta es c.itemid. Todo lo demás son valores fijos que no cambian.
  • Los índices están bien configurados y mysql elige los correctos para mí
    • entre ayb hay una relación 1: n (se usa el índice PRIMARY)
    • entre byc hay una relación de muchos a muchos (se usa el índice IDX_ITEMID)

el punto es que mysql debería comenzar a consultar la tabla a y trabajar para ir hacia c y no al revés. Cualquier cambio para lograr eso.

Solución: No es exactamente lo que quería pero esto parece funcionar:

SELECT c.* FROM table1 a INNER JOIN table2 b ON a.id = b.table1_id INNER JOIN table3 c ON b.itemid = c.itemid WHERE a.itemtype = 1 AND a.busy = 1 AND b.something = 0 AND b.acolumn = 2 AND c.itemid = 123456 AND f.id IN ( SELECT DISTINCT table2.id FROM table1 INNER JOIN table2 ON table1.id = table2.table1_id WHERE table1.itemtype = 1 AND table1.busy = 1)


Puedes intentar reescribir de dos maneras

  • trae algo de la condición DONDE a UNIR
  • Introducir subconsultas aunque no sean necesarias.

Ambas cosas podrían impactar al planificador.

Sin embargo, lo primero que debe verificar es si sus stats están actualizadas.


Puedes usar FORCE INDEX para forzar el orden de ejecución, y lo he hecho antes.

Si lo piensa, generalmente solo hay un orden en el que puede consultar las tablas para cualquier índice que elija.

En este caso, si desea que MySQL comience a consultar primero, asegúrese de que el índice que fuerza en b sea ​​uno que contenga b.table1_id . MySQL solo podrá usar ese índice si ya se ha consultado primero.


Quizás necesites usar STRAIGHT_JOIN .

http://dev.mysql.com/doc/refman/5.0/en/join.html

STRAIGHT_JOIN es similar a JOIN , excepto que la tabla izquierda siempre se lee antes que la tabla derecha. Esto se puede usar para aquellos (pocos) casos en los que el optimizador de combinación coloca las tablas en el orden incorrecto.