Digamos que tenemos un índice en (A, B) y un índice en (B, C). Al hacer una consulta como:
SELECT * FROM table WHERE A = const AND B = const ORDER BY C DESC¿El optimizador de consultas buscará primero en el índice (A,B) para filtrar las filas de la clase WHERE y luego utilizará el índice (B,C) para ordenar rápidamente?
¿O las consultas están restringidas a un índice? ¿Sin saltos de árbol B?
No, MySQL no hace lo que estás describiendo.
Hará uno de los siguientes:
Lea del índice (A, B) , que usará el índice para examinar solo las filas que coincidan, pero requiere trabajo adicional para hacer la ordenación de archivos para ordenar las filas por C .
Lea del índice (B, C) , que leerá las filas en el orden correcto y, por lo tanto, omitirá la ordenación de archivos. Pero examinará muchas filas adicionales que tienen valores de A que no coinciden, y tendrá que evaluar esas filas una por una y descartar las que no coincidan.
Puede optimizar para ambos reemplazando el índice (A, B) con un índice en (A, B, C) , esto examinará solo las filas coincidentes y las leerá en el orden deseado, por lo que no se necesita ordenar archivos.
InnoDB siempre lee filas en algún orden de índice. Un índice secundario o el índice agrupado.
Re sus preguntas:
En general, MySQL solo lee de un índice por referencia de tabla. Esto permite, por ejemplo, consultas con autounión, por lo que hay más de una referencia de tabla para la misma tabla. Cada referencia de tabla puede leerse usando un índice diferente.
Por ejemplo, una autounión de gerentes a sus empleados:
SELECT ... FROM employees AS m JOIN employees AS e ON e.manager_id = m.id WHERE m.hire_date = '2020-01-01' En este ejemplo, podría usar un índice en hire_date para seleccionar los gerentes y un índice en manager_id para los subordinados de los gerentes. Estas son dos referencias de tablas diferentes, por lo que se leen por separado.
También hay una característica de MySQL llamada optimización de combinación de índices , en la que podría leer dos subconjuntos de la tabla, potencialmente usando diferentes índices, y luego combinar los resultados usando una unión o una intersección. Pero encuentro que esto no sucede tan a menudo como podría pensarse.
Con respecto a ORDEN POR DESC,https://dev.mysql.com/doc/refman/8.0/en/descending-indexes.html dice:
anteriormente, los índices se podían escanear en orden inverso pero con una penalización en el rendimiento.
En MySQL 8.0, implementaron soporte para declarar que un índice se construye en orden descendente, para admitir consultas ORDER BY DESC. Pero luego el índice se adapta a esas consultas, y el uso del mismo índice para las consultas ASC sufriría. Por lo tanto, es posible que deba crear ambos índices en las mismas columnas de la misma tabla. Lea la página del documento a la que me vinculé para obtener más detalles.
Por supuesto, puede probar sus datos. Pero en mi experiencia, el índice primero coincidirá con la cláusula where . Por lo tanto, coincidirá con el índice (A, B) .
A continuación, realizará una clasificación para el pedido.
Usted pregunta:
¿El optimizador de consultas buscará primero en el índice (A,B) para filtrar las filas de la clase WHERE?
Sí, MySQL probablemente usará el primer índice para recuperar las filas usando un "Escaneo de rango de índice" con predicados de inicio y parada, o una "Búsqueda de índice", si el predicado coincide con una restricción UNIQUE .
... y luego usar el índice (B, C) para ordenar rápidamente?
No. Este segundo índice no incluye las filas filtradas utilizando el primer índice. El motor recuperará todas las filas (ya no se canalizará), las ordenará y luego se las proporcionará. Si hay muchas filas, esta fase requerirá muchos recursos y será lenta. Con suerte, el predicado de filtrado da como resultado solo unas pocas filas.