mysql> CREATE TABLE `t` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `a` (`a`), KEY `b` (`b`) ) ENGINE=InnoDBhay una tabla llamada t y tiene dos índices llamados a y b. Insertar en t 100000 filas de datos
mysql> create procedure idata() begin declare i int; set i=1; while(i<=100000)do insert into t values(i, i, i); set i=i+1; end while; end; Query OK, 0 rows affected (0.01 sec) mysql> delimiter ; mysql> call idata();Hago algunos experimentos, algunos son los siguientes

Ahora, quiero saber;
(1) por qué explain select * from t where a >= 90000; extra está Using index condition ? tiene clave de índice, pero no tiene filtro de índice ni filtro de tabla, entonces, ¿por qué está Using index condition ?
(2) por qué explain select * from t where a = 90000; adicional es NULL ? es necesario tener acceso a la tabla, si el primer caso está Using index condition , ¿por qué el segundo no puede estar Using index condition ?
(3) por qué explain select a from t where a >= 90000; extra es Using where; Using index ¿ Using where; Using index ? Sé que usa el índice de portada, por lo que extra tiene el Using index ; pero ¿por qué extra tiene el Using where ? ¿Significa que el servidor necesita filtrar los datos? pero el motor de almacenamiento ya ha devuelto lo correcto, ¿por qué el servidor necesita archivar?
Primero, la terminología...
"Usar índice" significa que (en este caso) INDEX(a) contiene todas las columnas necesarias. Eso es "el índice está cubriendo".
"Usar la condición de índice" es bastante diferente. Internamente, se llama ICP (Index Condition Pushdown). Esto se refiere a si el "manejador" verifica la expresión o si la "condición" (a >= 90000) se entrega al motor (InnoDB) para que haga el trabajo.
En cuanto a "Usar donde"; eso sigue siendo un misterio para mí, incluso después de usar MySQL durante 20 años y buscar miles de explicaciones. Lo ignoro.
En los 3 casos, se utiliza INDEX(a) . Esto se indica principalmente mediante "clave" ("a": el nombre de la clave, no de la columna), "key_len" ("5": INT de 4 bytes más 1 para NULLable ) y, en segundo lugar, mediante "tipo" ( que no dice "Todos").
Más lejos
Si cambia el 90000 a 70000, es posible que cambie a un escaneo de tabla. ¿Por qué rebotar entre el BTree del índice y el BTree de los datos (a través de la PRIMARY KEY ). El Optimizer asumirá que será más rápido simplemente escanear toda la tabla, ignorando las filas que fallan en la cláusula WHERE .
EXPLAIN FORMAT=JSON SELECT -- Te brinda mucha más información. (Quizás no haya mucha más información para esta simple consulta). Una sorpresa útil es que mostrará a cuántos tipos se refiere realmente la sola mención de "filesort". (Una forma posiblemente fácil de hacer que esto suceda es GROUP BY x ORDER BY y ; es decir, agrupar y ordenar por diferentes columnas).
Explique rara vez tiene números tan limpios, como su "10001". Por lo general, las columnas de "filas" son una aproximación, a veces un terrible aprox.
El registro lento registra "Filas examinadas"; probablemente dirá 10001 (o tal vez solo 10000) y 1 para sus pruebas. Para un escaneo de tabla, sería un total de 100K.
Otra forma de obtener "Filas examinadas" es a través de los valores de STATUS "Manejador". Ver http://mysql.rjweb.org/doc.php/index_cookbook_mysql#handler_counts
Su primera y última consulta utilizan WHERE con comparación implícita con otras filas, en ese caso utiliza el índice y lo muestra en el campo adicional (rango de tipo).
Cuando crea una condición con resultados 0-1, puede acceder directamente a ellos (búsqueda O(1)). No se compara ni se ordena, solo toma una fila, devuélvela.