Mysql IN () против производительности UNION ALL - PullRequest
0 голосов
/ 10 октября 2018

Может ли кто-нибудь объяснить разницу в характеристиках производительности следующих двух запросов, если таковые имеются?

Запрос 1

SELECT id FROM users WHERE status IN(1, 6, 11, 13);

Запрос 2

(SELECT id FROM users WHERE status = 1)
UNION ALL
(SELECT id FROM users WHERE status = 6)
UNION ALL
(SELECT id FROM users WHERE status = 11)
UNION ALL
(SELECT id FROM users WHERE status = 13)

Я в курсеэтот запрос № 1 гораздо более читабелен для человека.

Мне интересно обсуждение того, как их характеристики производительности могут быть одинаковыми или разными.Вы можете предположить, что существует индекс на users.status

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

С индексом оба должны быть по существу эквивалентны с точки зрения производительности.Основной процесс, когда доступен индекс, - это поиск по индексу, чтобы получить соответствующие строки и затем извлечь страницы данных.Первый делает это четыре раза в пределах одного блока запроса.Второй делает четыре блока запроса на один идентификатор.

Без индекса первый должен быть быстрее - до четырех раз быстрее, если необходимо каждый раз читать таблицу с диска.Или просто постепенно, если таблица помещается в доступную память, а последующие сканирования используют кеш страниц с теплыми данными.

0 голосов
/ 10 октября 2018

Первый будет быстрее.Это можно увидеть с помощью профилирования:

mysql> SET profiling = 1;
mysql> select * from bigtable where id in (200, 900, 22000, 88888);
mysql> select * from bigtable where id =200
-> union all
-> select * from bigtable where id =900
-> union all
-> select * from bigtable where id =22000
-> union all
-> select * from bigtable where id =88888;
mysql> show profile for query 1;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000046 |
| checking permissions | 0.000006 |
| Opening tables       | 0.000013 |
| init                 | 0.000024 |
| System lock          | 0.000008 |
| optimizing           | 0.000009 |
| statistics           | 0.000031 |
| preparing            | 0.000010 |
| executing            | 0.000003 |
| Sending data         | 0.000072 |
| end                  | 0.000004 |
| query end            | 0.000006 |
| closing tables       | 0.000006 |
| freeing items        | 0.000013 |
| cleaning up          | 0.000008 |
+----------------------+----------+
15 rows in set, 1 warning (0,00 sec)

mysql> show profile for query 2;
+----------------------+----------+                                                                                                                                 
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000054 |
| checking permissions | 0.000006 |
| checking permissions | 0.000002 |
| checking permissions | 0.000003 |
| checking permissions | 0.000004 |
| Opening tables       | 0.000112 |
| init                 | 0.000058 |
| System lock          | 0.000009 |
| optimizing           | 0.000008 |
| statistics           | 0.000032 |
| preparing            | 0.000009 |
| optimizing           | 0.000005 |
| statistics           | 0.000017 |
| preparing            | 0.000005 |
| optimizing           | 0.000005 |
| statistics           | 0.000014 |
| preparing            | 0.000005 |
| optimizing           | 0.000005 |
| statistics           | 0.000014 |
| preparing            | 0.000006 |
| executing            | 0.000003 |
| Sending data         | 0.000018 |
| executing            | 0.000003 |
| Sending data         | 0.000008 |
| executing            | 0.000003 |
| Sending data         | 0.000007 |
| executing            | 0.000003 |
| Sending data         | 0.000007 |
| end                  | 0.000004 |
| query end            | 0.000007 |
| removing tmp table   | 0.000009 |
| query end            | 0.000002 |
| closing tables       | 0.000008 |
| freeing items        | 0.000020 |
| cleaning up          | 0.000011 |
+----------------------+----------+
35 rows in set, 1 warning (0,00 sec)

Таким образом, накладные расходы на отдельные запросы внутри объединения существуют, даже если фактическое выполнение быстрое, так как запросы используют индекс.

0 голосов
/ 10 октября 2018

Во втором запросе вы запрашиваете таблицу отдельно.Для каждого select он должен прочитать таблицу.При первом подходе он должен прочитать таблицу один раз.

С индексом производительность не будет сильно отличаться.

Без индекса при каждом чтении таблицы должно быть выполнено полное сканирование таблицы иразница в производительности между этими двумя подходами будет еще больше.

Таким образом, первый запрос будет быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...