Mysql
 sql >> Base de données >  >> RDS >> Mysql

Le caractère générique dans la colonne la plus à gauche de l'index composite signifie-t-il que les colonnes restantes de l'index ne sont pas utilisées dans la recherche d'index (MySQL) ?

Voici vos questions. Pluriel. En les reformulant (avec "en d'autres termes"), ce sont juste des questions différentes. Cela ne facilite pas nécessairement la tâche des intervenants. Au contraire.

Q1 :[Question relative au titre] Le caractère générique dans la colonne la plus à gauche de l'index composite signifie-t-il que les colonnes restantes de l'index ne sont pas utilisées dans la recherche d'index (MySQL) ?

A1 :Non, ça ne veut pas dire ça.

Q2 :Le caractère générique utilisé dans la condition last_name signifie-t-il que la condition first_name ne sera pas utilisée pour aider davantage MySQL à trouver des index ?

A2 :Non, ça ne veut pas dire ça. De plus, la queue de cette question est ambiguë. Il sait déjà quel index utiliser pourrait être une réponse dérivée à un tel flou.

Q3 :En d'autres termes, en mettant un caractère générique sur la condition last_name, MySQL ne fera qu'une recherche partielle dans l'index (et ignorera les conditions données dans les colonnes à droite de last_name) ?

A3 : Non. Les colonnes les plus à droite sont servies à partir de l'index, de la même manière qu'une stratégie d'index de couverture bénéficiant de la lenteur de la recherche des pages de données.

Q4 :...l'Exemple-1 serait-il plus rapide que l'Exemple-2 ?

R4 :Oui. Il s'agit d'un index de couverture en ce qui concerne ces colonnes. Voir les index de couverture.

En aparté concernant Q4. Peu importe qu'il s'agisse d'un PK ou d'un non-PK. Il y a probablement une douzaine de raisons pour lesquelles cela en tant que PK serait épouvantable pour votre application.

Réponse(s) originale(s) ci-dessous :

avec uniquement une clé composée sur (last_name,first_name) et une requête comme vous le mentionnez

WHERE first_name LIKE 'joh%'

... Il n'utilisera pas du tout l'index. Il effectuera une analyse de table. En raison de l'absence de

  • une seule clé de colonne sur first_name
  • une clé composée avec first_name le plus à gauche

Alors scan de table nous voilà.

Veuillez consulter la page du manuel Index multi-colonnes pour en savoir plus. Et concentrez-vous sur le left-most concept de celui-ci. En fait, allez sur cette page et recherchez le mot left .

Voir la page du manuel sur Explain installation dans mysql. Aussi l'article Utilisation d'Explain pour écrire de meilleures requêtes Mysql .

Modifier

Il y a eu quelques modifications à la question depuis que je suis ici il y a une heure ou deux. Je vous laisse avec ce qui suit. Exécutez votre requête réelle via expliquer et déchiffrez via le Using Explain ... lien ci-dessus ou une autre référence

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 affiche les nombres vaudou pour les rows . Vaudou? Oui, car une requête qui durera potentiellement une heure, vous demandez explain pour vous donner un compte flou, ne pas l'exécuter, et vous donner cette réponse en 2 secondes ou moins. Ne les considérez pas comme des nombres réels de critères lorsqu'ils sont exécutés pour de vrai, sans 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 |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+