Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Leistungseinbuße für verschachtelte MySQL-Abfragen

Die Antwort auf diese Frage hängt davon ab, ob Sie mysql vor 5.7 oder 5.7 und später verwenden. Ich ändere Ihre Frage vielleicht etwas, aber das Folgende gibt hoffentlich wieder, worauf Sie hinauswollen.

Ihre SELECT * FROM Table führt einen Tabellenscan über den gruppierten Index (die physische Reihenfolge) durch. Falls kein Primärschlüssel vorhanden ist, ist einer implizit dem Motor zur Verfügung. Es gibt keine Where-Klausel, wie Sie sagen. Es wird nicht versucht, einen anderen Index zu filtern oder auszuwählen.

Die Erklärung Ausgabe (siehe auch ) zeigt 1 Zeile in seiner Zusammenfassung. Es ist relativ geradlinig. Erklären Sie Ausgabe und Leistung mit Ihrer abgeleiteten Tabelle B hängt davon ab, ob Sie eine Version vor 5.7 oder 5.7 und später verwenden.

Das Dokument Abgeleitete Tabellen in MySQL 5.7 beschreibt dies gut für die Versionen 5.6 und 5.7, wobei letztere keinen Nachteil aufgrund der Änderung der materialisierten abgeleiteten Tabellenausgabe bieten, die in die äußere Abfrage integriert wird. In früheren Versionen wurde bei temporären Tabellen mit dem abgeleiteten.

ein erheblicher Overhead in Kauf genommen

Es ist ziemlich einfach, die Leistungseinbußen vor 5.7 zu testen. Alles, was Sie brauchen, ist eine mittelgroße Tabelle, um die spürbaren Auswirkungen zu sehen, die die abgeleitete Tabelle Ihrer Frage auf die Leistung hat. Das folgende Beispiel bezieht sich auf eine kleine Tabelle in Version 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                                        |
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+

Beachten Sie, dass ich die Frage geändert habe, aber sie veranschaulicht die Auswirkungen, die abgeleitete Tabellen und ihre fehlende Indexverwendung mit dem Optimierer in Versionen vor 5.7 haben. Die abgeleitete Tabelle profitiert von Indizes, während sie materialisiert wird. Danach bleibt es jedoch als temporäre Tabelle im Overhead und wird ohne Indexverwendung in die äußere Abfrage integriert. Dies ist in Version 5.7

nicht der Fall