Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Kara wydajności dla zagnieżdżonych zapytań mysql

Odpowiedź na to pytanie zależy od tego, czy używasz mysql przed 5.7, czy 5.7 i później. Być może nieco zmienię twoje pytanie, ale mam nadzieję, że poniższe uchwyci to, czego szukasz.

Twój SELECT * FROM Table skanuje tabelę za pomocą indeksu klastrowego (fizycznej kolejności). W przypadku braku klucza podstawowego, jednym z nich jest niejawnie dostępne dla silnika. Nie ma klauzuli gdzie, jak mówisz. Nie podjęto próby filtrowania ani wyboru innego indeksu.

Wyjaśnij dane wyjściowe (patrz również ) pokazuje w podsumowaniu 1 wiersz. To jest stosunkowo proste. Wyjaśnij dane wyjściowe i wydajność za pomocą tabeli pochodnej B będzie się różnić w zależności od tego, czy korzystasz z wersji przed 5.7, czy 5.7 i później.

Dokument Tabele pochodne w MySQL 5.7 opisuje to dobrze dla wersji 5.6 i 5.7, gdzie ta ostatnia nie zapewni żadnej kary ze względu na zmianę danych wyjściowych zmaterializowanej tabeli pochodnej, która jest włączana do zapytania zewnętrznego. W poprzednich wersjach znaczne obciążenie było znoszone w przypadku tabel tymczasowych z danymi pochodnymi.

Bardzo łatwo jest przetestować spadek wydajności przed wersją 5.7. Wystarczy średniej wielkości tabela, aby zobaczyć zauważalny wpływ tabeli pochodnej pytania na wydajność. Poniższy przykład znajduje się na małym stoliku w wersji 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                                        |
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+

Zauważ, że zmieniłem pytanie, ale ilustruje ono wpływ, jaki mają tabele pochodne i ich brak użycia indeksu w optymalizatorze w wersjach wcześniejszych niż 5.7. Tabela pochodna korzysta z indeksów, gdy jest materializowana. Ale później jest to tabela tymczasowa i jest włączana do zewnętrznego zapytania bez użycia indeksu. Tak nie jest w wersji 5.7




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak wydrukować wszystkie pola dla wszystkich tabel w bazie mysql?

  2. MySQL - Jak sumować czasy?

  3. Elegancki sposób na usunięcie osieroconych wierszy?

  4. Mysql DISTINCT nie działa, jeśli dodam kolejną kolumnę

  5. Jak połączyć się z MySQL na Amazon EC2 z poziomu Windows?