Почему индексированный запрос mysql, отфильтрованный по меньшим значениям символов, приводит к большему количеству проверенных строк? - PullRequest
1 голос
/ 28 апреля 2020

Когда я запускаю следующий запрос, я вижу ожидаемые строки, проверенные как 40

EXPLAIN SELECT s.* FROM subscription s
WHERE s.current_period_end_date <= NOW()
AND s.status in ('A', 'T')
AND s.period_end_action in ('R','C')
ORDER BY s._id ASC limit 20;

+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys                  | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | s     | index | status,current_period_end_date | PRIMARY | 4       | NULL |   40 | Using where |
+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+

Но когда я запускаю этот запрос, который просто меняет AND s.period_end_action in ('R','C') на AND s.period_end_action = 'C', я вижу ожидаемые строки, проверенные как 611

EXPLAIN SELECT s.* FROM subscription s
WHERE s.current_period_end_date <= NOW()
AND s.status in ('A', 'T')
AND s.period_end_action = 'C'
ORDER BY s._id ASC limit 20;

+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys                  | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | s     | index | status,current_period_end_date | PRIMARY | 4       | NULL |  611 | Using where |
+----+-------------+-------+-------+--------------------------------+---------+---------+------+------+-------------+

У меня есть следующие индексы в таблице подписки:

_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
INDEX(status, period_end_action),
INDEX(current_period_end_date),

Есть идеи? Я не понимаю, почему удаление одного из значений period_end_action может привести к такому большому увеличению количества проверенных строк?

1 Ответ

0 голосов
/ 30 апреля 2020

(я согласен с другими, что EXPLAIN часто имеет ужасные оценки строк.)

На самом деле цифры могут быть разумными (хотя я сомневаюсь в этом). Оптимизатор решил сделать сканирование таблицы в обоих случаях. И запрос с меньшим количеством вариантов для period_end_action, вероятно, должен сканировать дальше, чтобы получить 20 строк. Это связано с тем, что он использует один из ваших вторичных индексов.

Эти индексы с большей вероятностью помогут вашему второму запросу:

INDEX(period_end_action, _id)
INDEX(period_end_action, status)
INDEX(period_end_action, current_period_end_date)

Оптимальный индекс равен обычно начинается с любых столбцов, проверенных =.

Поскольку для вашего первого запроса такого не существует, оптимизатор, вероятно, решил сканировать в порядке _id, чтобы избежать «сортировать» по мандату ORDER BY.

...