Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Penalidade de desempenho para consultas mysql aninhadas


A resposta a esta pergunta depende se você está usando o mysql antes de 5.7 ou 5.7 e depois. Eu posso estar alterando sua pergunta um pouco, mas espero que o seguinte capture o que você está procurando.

Seu SELECT * FROM Table faz uma varredura de tabela por meio do índice clusterizado (a ordenação física). No caso de nenhuma chave primária, uma é implicitamente disponível para o motor. Não há cláusula where como você diz. Nenhuma filtragem ou escolha de outro índice é tentada.

A Explicar saída (veja também ) mostra 1 linha em seu resumo. É relativamente direto. A saída explicada e o desempenho com sua tabela derivada B será diferente dependendo se você estiver em uma versão anterior a 5.7 ou 5.7 e posterior.

O documento Tabelas Derivadas no MySQL 5.7 descreve-o bem para as versões 5.6 e 5.7, onde o último não fornecerá penalidade devido à alteração na saída da tabela derivada materializada sendo incorporada à consulta externa. Nas versões anteriores, uma sobrecarga substancial era suportada com tabelas temporárias com o derivado.

É muito fácil testar a penalidade de desempenho antes de 5.7. Basta uma tabela de tamanho médio para ver o impacto perceptível que a tabela derivada da sua pergunta tem no desempenho. O exemplo a seguir está em uma pequena tabela na versão 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                                        |
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+

Observe que alterei a pergunta, mas ela ilustra o impacto que as tabelas derivadas e a falta de uso do índice com o otimizador têm nas versões anteriores à 5.7. A tabela derivada se beneficia dos índices à medida que está sendo materializada. Mas, depois disso, ela sofre sobrecarga como uma tabela temporária e é incorporada à consulta externa sem uso de índice. Este não é o caso na versão 5.7