SQL - Граф все еще быстр с вложенными запросами? - PullRequest
0 голосов
/ 13 ноября 2018

Предположим, у меня есть запрос:

SELECT message.mid
FROM message
WHERE message.mid <= 100

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

SELECT COUNT(message.mid)
FROM message
WHERE message.mid <= 100

Но будет ли следующий запрос иметь такую ​​же выгоду? Будет ли все так же быстро?

SELECT COUNT(*)
FROM (
    SELECT message.mid,
           message.something,
           message.something2,
           message.something3,
    FROM message
    WHERE message.mid <= 100
) AS A

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

COUNT(*) говорит подсчитать строки.

COUNT(x) говорит, чтобы подсчитать строки, где x IS NOT NULL. Так что чуть медленнее, и, возможно, другой ответ.

SELECT mid (против SELECT COUNT(...)) - медленнее и громоздче. Он возвращает все значение mid, а не только одно число.

SELECT COUNT(..) FROM ( SELECT ... ) - намного медленнее (в более старых версиях MySQL), потому что он должен генерировать временную таблицу с результатом подзапроса. Кроме того, COUNT собирает просто простое число; подзапрос собирает много строк.

Если индексирован mid (включая PRIMARY KEY, то WHERE mid <= 100 - это сканирование диапазона (индекса) индекса (или таблицы). То есть касается только некоторых строк.

Если mid не проиндексирован, будет просканирована вся таблица - следовательно, медленнее.

0 голосов
/ 13 ноября 2018

Мы можем спросить MySQL, что он будет делать . Это 5,7.

mysql> explain SELECT COUNT(*) FROM (     SELECT message.mid     FROM message     WHERE message.mid <= 100 
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | message | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |  100 |   100.00 | Using where; Using index |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)


mysql> explain SELECT count(message.mid)     FROM message     WHERE message.mid <= 100;
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | message | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |  100 |   100.00 | Using where; Using index |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

Выглядит так же. MySQL оптимизировал удаление подзапроса.

Вот пример того, что мы увидим, когда MySQL не оптимизирует подзапрос.

mysql> explain SELECT * FROM (     SELECT message.mid     FROM message where mid < 100 group by mid) m;
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table      | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | PRIMARY     | <derived2> | NULL       | ALL   | NULL          | NULL    | NULL    | NULL |   99 |   100.00 | NULL                     |
|  2 | DERIVED     | message    | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |   99 |   100.00 | Using where; Using index |
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+

«Оптимизация производных таблиц и просмотр ссылок» содержит примеры того, как работает эта оптимизация.

Пример 1:

SELECT * FROM (SELECT * FROM t1) AS derived_t1;

При объединении этот запрос выполняется аналогично:

SELECT * FROM t1;

На этой странице описаны многие другие приемы оптимизации, которые MySQL использует для повышения эффективности подзапросов.

...