sql >> Databáze >  >> RDS >> Mysql

Pokuta za výkon za vnořené dotazy mysql

Odpověď na tuto otázku závisí na tom, zda používáte mysql před 5.7 nebo 5.7 a po něm. Možná trochu pozměním vaši otázku, ale doufejme, že následující vystihne to, co hledáte.

Vaše SELECT * FROM Table provádí skenování tabulky prostřednictvím seskupeného indexu (fyzické uspořádání). V případě žádného primárního klíče je jeden implicitně k dispozici motoru. Není tam žádná klauzule kde, jak říkáte. Nepokusíte se o žádné filtrování ani výběr jiného indexu.

Vysvětlení výstup (viz také ) zobrazuje ve svém souhrnu 1 řádek. Je to relativně přímočaré. Vysvětlení výstupu a výkonu s vaší odvozenou tabulkou B se bude lišit v závislosti na tom, zda používáte verzi před 5.7 nebo 5.7 a novější.

Dokument Odvozené tabulky v MySQL 5.7 popisuje to dobře pro verze 5.6 a 5.7, kde posledně jmenovaná nebude poskytovat žádnou penalizaci kvůli změně výstupu materializované odvozené tabulky, která je začleněna do vnějšího dotazu. V předchozích verzích byla značná režie snášena s dočasnými tabulkami s odvozeným.

Je docela snadné otestovat penalizaci výkonu před 5.7. Stačí jen středně velká tabulka, abyste viděli, jaký znatelný dopad má odvozená tabulka vaší otázky na výkon. Následující příklad je na malé tabulce ve verzi 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                                        |
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+

Všimněte si, že jsem otázku změnil, ale ilustruje dopad, který mají odvozené tabulky a jejich nedostatečné použití indexu s optimalizátorem ve verzích před 5.7. Odvozená tabulka těží z indexů při jejím zhmotňování. Poté však přetrvává režie jako dočasná tabulka a je začleněna do vnějšího dotazu bez použití indexu. To není případ verze 5.7




  1. Jak funguje sys.dm_exec_describe_first_result_set na serveru SQL Server

  2. Existuje v PostgreSQL něco jako funkce zip(), která kombinuje dvě pole?

  3. Jak vytvořit postgres rozšíření uvnitř kontejneru?

  4. Jak vložit emotikony do MYSQL 5.5 a vyšší pomocí Django ORM