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

Penalización de rendimiento para consultas mysql anidadas

La respuesta a esta pregunta depende de si está usando mysql antes de 5.7 o 5.7 y después. Puede que esté alterando un poco tu pregunta, pero espero que lo siguiente capte lo que buscas.

Tu SELECT * FROM Table hace un escaneo de la tabla a través del índice agrupado (el ordenamiento físico). En el caso de que no haya clave principal, una es implícitamente disponible para el motor. No hay cláusula where como usted dice. No se intenta filtrar ni elegir otro índice.

El Explicar salida (ver también ) muestra 1 fila en su resumen. Es relativamente sencillo. La explicación de la salida y el rendimiento con su tabla derivada B diferirá dependiendo de si tiene una versión anterior a la 5.7 o 5.7 y posteriores.

El documento Tablas Derivadas en MySQL 5.7 lo describe bien para las versiones 5.6 y 5.7, donde esta última no proporcionará penalización debido al cambio en la salida de la tabla derivada materializada que se incorpora a la consulta externa. En versiones anteriores, se soportaron gastos generales considerables con tablas temporales con el derivado.

Es bastante fácil probar la penalización de rendimiento antes de 5.7. Todo lo que se necesita es una tabla de tamaño mediano para ver el impacto notable que tiene la tabla derivada de su pregunta sobre el rendimiento. El siguiente ejemplo está en una pequeña mesa en la versión 5.6:

explain 
select qm1.title  
from questions_mysql qm1 
join questions_mysql qm2 
on qm2.qid<qm1.qid 
where qm1.qid>3333 and qm1.status='O';
+----+-------------+-------+-------+-----------------+---------+---------+------+-------+------------------------------------------------+
| id | select_type | table | type  | possible_keys   | key     | key_len | ref  | rows  | Extra                                          |
+----+-------------+-------+-------+-----------------+---------+---------+------+-------+------------------------------------------------+
|  1 | SIMPLE      | qm1   | range | PRIMARY,cactus1 | PRIMARY | 4       | NULL |  5441 | Using where                                    |
|  1 | SIMPLE      | qm2   | ALL   | PRIMARY,cactus1 | NULL    | NULL    | NULL | 10882 | Range checked for each record (index map: 0x3) |
+----+-------------+-------+-------+-----------------+---------+---------+------+-------+------------------------------------------------+


explain 
select b.title from 
(   select qid,title from questions_mysql where qid>3333 and status='O' 
) b 
join questions_mysql qm2 
on qm2.qid<b.qid; 
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+
| id | select_type | table           | type  | possible_keys   | key     | key_len | ref  | rows  | Extra                                              |
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+
|  1 | PRIMARY     | qm2             | index | PRIMARY,cactus1 | cactus1 | 10      | NULL | 10882 | Using index                                        |
|  1 | PRIMARY     | <derived2>      | ALL   | NULL            | NULL    | NULL    | NULL |  5441 | Using where; Using join buffer (Block Nested Loop) |
|  2 | DERIVED     | questions_mysql | range | PRIMARY,cactus1 | PRIMARY | 4       | NULL |  5441 | Using where                                        |
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+

Tenga en cuenta que cambié la pregunta, pero ilustra el impacto que tienen las tablas derivadas y su falta de uso de índices con el optimizador en versiones anteriores a la 5.7. La tabla derivada se beneficia de los índices a medida que se materializa. Pero a partir de entonces soporta la sobrecarga como una tabla temporal y se incorpora a la consulta externa sin uso de índice. Este no es el caso en la versión 5.7