Perché Mysql optimizer sceglie l'indice secondario quando esegue un 'select * from lookup' senza una clausola order by.Perché MySQL Query Optimizer sceglie l'indice secondario sull'indice primario clusterizzato?
È solo un colpo di fortuna o si tratta di un'ottimizzazione dietro le quinte che presuppone dal momento che è stato aggiunto un indice secondario più importante della chiave primaria.
Mi aspetto che i risultati vengano ordinati tramite chiave primaria poiché una scansione di tutti i nodi foglia può fornire tutti i dati necessari per rispondere a questa query.
di riprodurre creo una semplice tabella coppia chiave/valore (nota non auto_increment)
create table lookup (
id int not null,
primary key (id),
name varchar(25),
unique k_name (name)
) engine=innodb;
inserire alcuni dati in ordine non alfabetico casuale
insert into lookup values(1, "Zebra"),(2, "Aardvark"),(3, "Fish"),(4,"Dog"),(5,"Cat"),(6,"Mouse");
Query dei dati (questo è dove mi aspetto che i dati vengano restituiti in ordine di chiave primaria)
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)
Dove come non è - sembra che sia stata eseguita una scansione dei nodi foglia k_name. qui
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)
Per me mostrato questo dice Mysql sta usando k_name come un indice di copertura per restituire i dati. Se si rilascia l'indice k_name, i dati vengono restituiti nell'ordine delle chiavi primarie. Se aggiungo un'altra colonna non indicizzata, i dati vengono restituiti nell'ordine delle chiavi primarie.
Alcune informazioni di base sulla mia configurazione.
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 è un indice secondario. La definizione della chiave Candidate non ha nulla a che fare con gli indici. Anche una chiave primaria per definizione non ha nulla a che fare con gli indici. Tuttavia, la maggior parte dei DBMS crea automaticamente un indice per te quando definisci una chiave primaria. –
k_name NON È UN INDICE SECONDARIO A TUTTI.Poiché si tratta di una chiave univoca, si comporta esattamente come fa una CHIAVE PRIMARIA. Le chiavi univoche sono, in realtà, indici cluster definiti dall'utente. È tanto un indice cluster quanto una PRIMARY KEY. Anche se non esiste una chiave primaria, un gen_clust_index basato su rowid viene generato internamente. La prova di ciò si trova in InnoDB. Puoi fare ORDER BY colonne chiave primaria contro MyISAM tutto il giorno. In InnoDB, non puoi né riordinare CHIAVI UNICHE né mitigare le query SELECT senza ORDER in favore di PRIMARY KEY rispetto ad altri CHIAVI UNICHE. Gli indici secondari non sono mai unici. – RolandoMySQLDBA
L'indice cluster è quello della chiave PRIMARY. MySQL utilizza solo indici UNICI non nulli come indice cluster quando non esiste la chiave primaria. Inoltre, solo gli indici secondari come k_name includono anche dati di chiavi primarie per fare riferimento alle righe corrispondenti. Lo vedrai quando aggiungi un'altra colonna e k_name non è in grado di fornire tutti i dati come fa l'indice cluster. http://dev.mysql.com/doc/innodb/1.1/en/glossary.html#glos_secondary_index k_name diventa un indice cluster quando viene rimossa la chiave primaria. –