sql >> Base de Datos >  >> RDS >> Mysql

¿El comodín en la columna más a la izquierda del índice compuesto significa que las columnas restantes en el índice no se usan en la búsqueda de índice (MySQL)?

Aquí están sus preguntas. Plural. Al reformularlos (con "en otras palabras") son solo preguntas diferentes. Hacerlo no lo hace necesariamente más fácil para los respondedores. Al contrario.

P1:[Pregunta del título] ¿El comodín en la columna más a la izquierda del índice compuesto significa que las columnas restantes en el índice no se usan en la búsqueda de índice (MySQL)?

A1:No, no significa eso.

P2:¿El comodín utilizado en la condición last_name significa que la condición first_name no se utilizará para ayudar a MySQL a encontrar índices?

A2:No, no significa eso. Además, la cola de esa pregunta es ambigua. Ya sabe qué Index usar podría ser una respuesta indirecta a tal vaguedad.

P3:En otras palabras, al colocar un comodín en la condición apellido, MySQL solo realizará una búsqueda de índice parcial (e ignorará las condiciones dadas en las columnas que están a la derecha de apellido)?

R3:No. Las columnas más a la derecha se sirven desde el índice de forma similar a una estrategia de índice de cobertura que se beneficia de la lentitud de la búsqueda de páginas de datos.

P4:...¿el Ejemplo-1 sería más rápido que el Ejemplo-2?

A4:Sí. Es un índice de cobertura con respecto a esas columnas. Ver índices de cobertura.

Como un aparte sobre Q4. Es irrelevante si es un PK o no PK. Probablemente hay una docena de razones por las que eso como PK sería terrible para su aplicación.

Respuesta(s) original(es) a continuación:

con solo una clave compuesta en (last_name,first_name) y una consulta como mencionas

WHERE first_name LIKE 'joh%'

... No usará el índice en absoluto. Hará un escaneo de la tabla. Debido a la ausencia de

  • una clave de una sola columna en first_name
  • una clave compuesta con first_name más a la izquierda

Así que vamos a escanear la tabla.

Consulte la página del manual Índices de varias columnas para leer más Y enfócate en el left-most concepto de ello. De hecho, vaya a esa página y busque la palabra left .

Consulte la página del manual en Explicar instalación en mysql. También el artículo Using Explain to Write Better Mysql Queries .

Editar

Ha habido algunas modificaciones a la pregunta desde que estuve aquí hace una o dos horas. Los dejo con lo siguiente. Ejecute su consulta real a través de la explicación y descifre a través de Using Explain ... enlace anterior u otra referencia

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 muestra números de vudú para rows . ¿Vudú? Sí, porque una consulta que potencialmente se ejecutará durante una hora, está preguntando explain para darle un conteo borroso, no ejecutarlo, y darle esa respuesta en 2 segundos o menos. No considere que estos sean # de conteo real para los criterios cuando se ejecuta de verdad, sin 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 |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+