Индекс MySQL не используется при возврате определенных столбцов - PullRequest
0 голосов
/ 11 ноября 2019

У меня есть таблица с полем created_on, которое индексируется само по себе. Глядя на медленный запрос, я понял, что в зависимости от того, какой столбец я возвращаю, индекс не используется. В следующих двух примерах у меня есть столбцы foo и bar.

  • foo является частью другого индекса с тремя другими столбцами.
  • bar вообще не индексируется.

EXPLAIN SELECT created_on, foo FROM T1
WHERE created_on > NOW() - INTERVAL 5 DAY;

Индекс не используется, +3 мил строки ищутся. (Using where)

Если я добавлю предложение LIMIT, будет использовать индекс.

EXPLAIN SELECT created_on, foo FROM T1
WHERE created_on > NOW() - INTERVAL 5 DAY
LIMIT 1000;

При использовании другого столбца barон также будет использовать индекс.

EXPLAIN SELECT created_on, bar FROM T1
WHERE created_on > NOW() - INTERVAL 5 DAY;

Используется индекс, и выполняется поиск только в 1,5 млн. строк. (Using where; Using index)

Почему MySQL пропускает индекс для одного из этих запросов?

1 Ответ

2 голосов
/ 12 ноября 2019
SELECT created_on, foo FROM T1
WHERE created_on > NOW() - INTERVAL 5 DAY;

Оптимизатор может использовать или не использовать INDEX(created_on). Это зависит от того, какой процент таблицы составляют строки, созданные за последние 5 дней. Будет использоваться небольшой процент (скажем, 20%), индекс будет использоваться.

С другой стороны, INDEX(created_on, foo) (в этом порядке), поскольку он будет «покрывать».

foo является частью другого индекса с тремя другими столбцами.

Порядок столбцов в индексе очень важный. Пожалуйста, укажите SHOW CREATE TABLE, если вам нужно дальнейшее обсуждение.

, если использовать другую строку столбца, он также будет использовать индекс.

Этот индекс может быть PRIMARY KEY. Пожалуйста, укажите SHOW CREATE TABLE, если вам нужно дальнейшее обсуждение.

(Использование где; Использование индекса)

«Использование индекса» означает, что все необходимые столбцы находятся в указателе. Следовательно, нужно рассматривать только BTree индекса. Каждый вторичный индекс неявно включает в себя столбцы PRIMARY KEY. Итак, я делаю вывод, что у вас есть INDEX(bar) и created_at где-то в PRIMARY KEY.

Почему MySQL пропускает индекс для одного из этих запросов?

Оптимизатор спрашивает, что будет быстрее (а обычно дает правильный ответ):

  • Индекс "покрытие", так что давайтеиспользуйте только индекс.
  • Давайте использовать индекс, но отскок между ним и BTree данных, чтобы получить другие столбцы.
  • Я ничего не могу сделать с WHERE, но яможно использовать индекс для ORDER BY;давайте сделаем это и надеемся, что мне не придется сканировать слишком много строк.
  • Пунт. Давайте проигнорируем все индексы и просто просканируем данные, отбрасывая все строки, которые не соответствуют предложению WHERE.

Да, последний вариант часто самый быстрый. Некоторые возможные характеристики:

  • Никакой вторичный индекс не очень помогает с WHERE.
  • Существует WHERE, но он не устраняет много строк.
  • Нет ORDER BY, или ни один индекс не соответствует ему.
  • Нет LIMIT.

При использовании MySQL EXPLAIN FORMAT=JSON SELECT ... обеспечит вычисления на основе затрат, которые он сделал дляпринять решение.

Моя кулинарная книга помогает построить оптимальные индексы.

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