¿Por qué el optimizador de Mysql elige el índice secundario al hacer un 'select * from lookup' sin cláusula order by.¿Por qué MySQL Query Optimizer elige el índice secundario sobre el índice primario agrupado?
¿Es solo una casualidad o esta es una optimización entre bastidores que se supone, ya que agregó un índice secundario es más importante que la clave principal.
Espero que los resultados se ordenen por clave principal ya que un escaneo de todos los nodos hoja puede proporcionar todos los datos necesarios para responder esta consulta.
para reproducir creo una sencilla tabla de clave/valor par (Nota no AUTO_INCREMENT)
create table lookup (
id int not null,
primary key (id),
name varchar(25),
unique k_name (name)
) engine=innodb;
insertar algunos datos en orden no-alfabético al azar
insert into lookup values(1, "Zebra"),(2, "Aardvark"),(3, "Fish"),(4,"Dog"),(5,"Cat"),(6,"Mouse");
consultar los datos (aquí es donde Esperaría que los datos se devuelvan en orden de clave principal)
mysql> select * from lookup;
+----+----------+
| id | name |
+----+----------+
| 2 | Aardvark |
| 5 | Cat |
| 4 | Dog |
| 3 | Fish |
| 6 | Mouse |
| 1 | Zebra |
+----+----------+
6 rows in set (0.00 sec)
Donde como no lo es, parece que se ha realizado un escaneo de los nodos de la hoja k_name. Se muestra aquí
mysql> explain select * from lookup;
+----+-------------+--------+-------+---------------+--------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+--------+---------+------+------+-------------+
| 1 | SIMPLE | lookup | index | NULL | k_name | 28 | NULL | 6 | Using index |
+----+-------------+--------+-------+---------------+--------+---------+------+------+-------------+
1 row in set (0.00 sec)
Para mí esto dice MySQL está usando k_name como un índice de cobertura para devolver los datos. Si elimino el índice k_name, los datos se devuelven en orden de clave primaria. Si agrego otra columna no indexada, los datos se devuelven en orden de clave primaria.
Alguna información básica sobre mi configuración.
mysql> show table status like 'lookup'\G
*************************** 1. row ***************************
Name: lookup
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 6
Avg_row_length: 2730
Data_length: 16384
Max_data_length: 0
Index_length: 16384
Data_free: 0
Auto_increment: NULL
Create_time: 2011-11-15 10:42:35
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
mysql> select version();
+------------+
| version() |
+------------+
| 5.5.15-log |
+------------+
1 row in set (0.00 sec)
k_name es un índice secundario. La definición de clave Candidato no tiene nada que ver con los índices. Incluso una clave principal por definición no tiene nada que ver con los índices. Sin embargo, la mayoría de los DBMS crean automáticamente un índice para usted cuando define una clave principal. –
k_name NO ES UN ÍNDICE SECUNDARIO.Como es una clave única, se comporta exactamente como lo hace una PRIMARY KEY. Las claves únicas son, en realidad, índices agrupados definidos por el usuario. Es tanto un índice agrupado como una PRIMARY KEY. Incluso si no existe una clave principal, se genera internamente un gen_clust_index basado en rowid. La prueba de esto yace en InnoDB. Puede hacer ORDER BY columnas de clave primaria contra MyISAM durante todo el día. En InnoDB, no puede reordenar las TECLAS ÚNICAS ni mitigar las consultas SELECCIONAR SIN PEDIDOS a favor de la LLAVE PRIMARIA sobre otras LLAVES ÚNICAS. Los índices secundarios nunca son únicos. – RolandoMySQLDBA
El índice agrupado es el de la tecla PRIMARIO. MySQL solo usa índices ÚNICOS no nulos como índice agrupado cuando NO hay ninguna clave principal. Además, solo los índices secundarios como k_name también incluyen datos de clave primaria para referenciar las filas correspondientes. Verá que cuando agrega otra columna y k_name no puede proporcionar todos los datos como lo hace el índice agrupado. http://dev.mysql.com/doc/innodb/1.1/en/glossary.html#glos_secondary_index k_name se convierte en un índice agrupado cuando se elimina la clave principal. –