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

Penalità di prestazioni per query MySQL nidificate

La risposta a questa domanda dipende dal fatto che stai usando mysql prima della 5.7 o 5.7 e successive. Potrei modificare leggermente la tua domanda, ma spero che quanto segue catturi ciò che stai cercando.

Il tuo SELECT * FROM Table esegue una scansione della tabella tramite l'indice cluster (l'ordinamento fisico). In caso di nessuna chiave primaria, una è implicitamente a disposizione del motore. Non c'è una clausola dove come dici tu. Non viene tentato alcun filtraggio o scelta di un altro indice.

La Spiega output (vedi anche ) mostra 1 riga nel riepilogo. È relativamente semplice. Spiega l'output e le prestazioni con la tua tabella derivata B differirà a seconda che tu stia utilizzando una versione precedente alla 5.7 o 5.7 e successive.

Il documento Tabelle derivate in MySQL 5.7 lo descrive bene per le versioni 5.6 e 5.7, dove quest'ultima non fornirà alcuna penalità a causa della modifica dell'output della tabella derivata materializzato incorporato nella query esterna. Nelle versioni precedenti, con tabelle temporanee con il derivato, veniva sopportato un sovraccarico sostanziale.

È abbastanza facile testare la penalità di prestazione prima della 5.7. Tutto ciò che serve è una tabella di medie dimensioni per vedere l'impatto notevole che la tabella derivata della tua domanda ha sull'impatto sulle prestazioni. L'esempio seguente è su una piccola tabella nella versione 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                                        |
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+

Nota, ho cambiato la domanda, ma illustra l'impatto che le tabelle derivate e la loro mancanza di utilizzo dell'indice con l'ottimizzatore hanno nelle versioni precedenti alla 5.7. La tabella derivata beneficia degli indici mentre viene materializzata. Ma in seguito subisce un sovraccarico come tabella temporanea e viene incorporato nella query esterna senza l'uso dell'indice. Questo non è il caso della versione 5.7