Mysql
 sql >> Database >  >> RDS >> Mysql

Il carattere jolly nella colonna più a sinistra dell'indice composito indica che le colonne rimanenti nell'indice non vengono utilizzate nella ricerca nell'indice (MySQL)?

Ecco le tue domande. Plurale. Riformulandoli (con "in altre parole") sono solo domande diverse. Ciò non rende necessariamente più facile per i soccorritori. Al contrario.

Q1:[Domanda sul titolo] Il carattere jolly nella colonna più a sinistra dell'indice composto significa che le colonne rimanenti nell'indice non vengono utilizzate nella ricerca nell'indice (MySQL)?

A1:No, non significa questo.

Q2:Il carattere jolly utilizzato nella condizione last_name significa che la condizione first_name non verrà utilizzata per aiutare ulteriormente MySQL a trovare gli indici?

A2:No, non significa questo. Inoltre la coda di quella domanda è ambigua. Sa già quale indice utilizzare potrebbe essere una risposta derivata a tale vaghezza.

Q3:In altre parole, inserendo un carattere jolly sulla condizione last_name MySQL eseguirà solo una ricerca parziale nell'indice (e ignorerà le condizioni fornite nelle colonne a destra di last_name)?

R3:No. Le colonne più a destra sono servite dall'indice in modo simile a una strategia di indice di copertura che beneficia della lentezza della ricerca nella pagina dei dati.

Q4:...l'Esempio-1 sarebbe più veloce dell'Esempio-2?

R4:Sì. È un indice di copertura rispetto a quelle colonne. Vedi indici di copertura.

Per inciso riguardo al quarto trimestre. È irrilevante se si tratta di un PK o non PK. Ci sono probabilmente una dozzina di motivi per cui questo come PK sarebbe terribile per la tua applicazione.

Risposte originali di seguito:

con solo una chiave composta su (last_name,first_name) e una domanda come dici tu

WHERE first_name LIKE 'joh%'

... Non utilizzerà affatto l'indice. Farà una scansione della tabella. A causa dell'assenza di

  • una chiave di colonna singola su first_name
  • una chiave composta con first_name più a sinistra

Quindi la scansione della tabella ecco che arriviamo.

Consulta la pagina del manuale Indici a colonne multiple per leggere di più. E concentrati sul left-most concetto di esso. Infatti, vai su quella pagina e cerca la parola left .

Consulta la pagina del manuale su Spiega struttura in MySQL Anche l'articolo Utilizzare Explain per scrivere query MySQL migliori .

Modifica

Ci sono state alcune modifiche alla domanda da quando ero qui un'ora o due fa. Ti lascio con quanto segue. Esegui la tua query effettiva attraverso spiegare e decifrare tramite Using Explain ... link sopra o un altro riferimento

drop table myNames;
create table myNames
(   id int auto_increment primary key,
    lastname varchar(100) not null,
    firstname varchar(100) not null,
    col4 int not null,
    key(lastname,firstname)
);
truncate table myNames;
insert myNames (lastName,firstName,col4) values
('Smith','John',1),('Smithers','JohnSomeone',1),('Smith3','John4324',1),('Smi','Jonathan',1),('Smith123x$FA','Joh',1),('Smi3jfif','jkdid',1),('r3','fe2',1);

insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;

select count(*) from myNames; 
-- 458k rows

select count(*)
from myNames
where lastname like 'smi%';
-- 393216 rows

select count(*)
from myNames
where lastname like 'smi%' and firstname like 'joh%';
-- 262144 rows

Explain rende i numeri voodoo per rows . Voodoo? Sì, perché una query che potrebbe durare un'ora, stai chiedendo explain per darti un conteggio sfocato, non eseguirlo e darti quella risposta in 2 secondi o meno. Non considerarli come numeri di conteggio reali per i criteri quando viene eseguito per davvero, senza explain .

explain 
select count(*) 
from myNames 
where lastname like 'smi%';
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
| id | select_type | table   | type  | possible_keys | key      | key_len | ref  | rows   | Extra                    |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | myNames | range | lastname      | lastname | 302     | NULL | 233627 | Using where; Using index |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+

explain 
select count(*) 
from myNames 
where lastname like 'smi%' and firstname like 'joh%' and col4=1;
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
| id | select_type | table   | type  | possible_keys | key      | key_len | ref  | rows   | Extra                    |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | myNames | range | lastname      | lastname | 604     | NULL | 233627 | Using where; Using index |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+


-- the below chunk is interest. Look at the Extra column

explain 
select count(*) 
from myNames 
where lastname like 'smi%' and firstname like 'joh%' and col4=1;
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | myNames | ALL  | lastname      | NULL | NULL    | NULL | 457932 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+

explain 
select count(*) 
from myNames 
where firstname like 'joh%';
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
| id | select_type | table   | type  | possible_keys | key      | key_len | ref  | rows   | Extra                    |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | myNames | index | NULL          | lastname | 604     | NULL | 453601 | Using where; Using index |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+


analyze table myNames;
+----------------------+---------+----------+----------+
| Table                | Op      | Msg_type | Msg_text |
+----------------------+---------+----------+----------+
| so_gibberish.mynames | analyze | status   | OK       |
+----------------------+---------+----------+----------+

select count(*) 
from myNames where left(lastname,3)='smi';
-- 393216 -- the REAL #
select count(*) 
from myNames where left(lastname,3)='smi' and left(firstname,3)='joh';
-- 262144 -- the REAL #

explain 
select lastname,firstname 
from myNames  
where lastname like 'smi%' and firstname like 'joh%';
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
| id | select_type | table   | type  | possible_keys | key      | key_len | ref  | rows   | Extra                    |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | myNames | range | lastname      | lastname | 604     | NULL | 226800 | Using where; Using index |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+