Индекс покрытия (и функциональный) MySQL 8.0.28 не используется

Я пытаюсь использовать индекс покрытия (с функциональным индексом) в MySQL 8.0.28, чтобы ускорить группировку по запросу в большой таблице InnoDB.

Индекс покрытия создан:

ALTER TABLE `sp_files`
ADD INDEX `ix_site_header_to_cleaned_text2` (`sp_site_foreign_key`, (length(`cleaned_text`)));

Используя только поля из покрывающего индекса, я ожидаю, что MySQL будет использовать индекс вместо базовой таблицы, поэтому я ожидаю, что в столбце Extra выходных данных EXPLAIN будет отображаться Using index:

EXPLAIN
SELECT sp_site_foreign_key,
    count(case when length(`cleaned_text`) > 100 then 1 else NULL END) as num1,
    count(1) as num2
FROM sp_files USE INDEX (`ix_site_header_to_cleaned_text2`)
GROUP by sp_site_foreign_key; 
идентификатор select_type стол перегородки тип возможные_ключи ключ key_len ссылка ряды фильтрованный Дополнительный 1 ПРОСТОЙ sp_files индекс ix_site_header_to_cleaned_text2 ix_site_header_to_cleaned_text2 208 105249 100

Есть идеи, почему он не использует индекс? Все поля запроса содержатся в индексе ix_site_header_to_cleaned_text2, поэтому я ожидаю, что explain отобразится Using index в столбце Extra.

Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
0
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не профессионал в MySQL, но что, если вы окружите ix_site_header_to_cleaned_text2 `` внутри FROM sp_files USE INDEX (ix_site_header_to_cleaned_text2)?

Спасибо, я только что попробовал - никакой разницы. Это имеет смысл, поскольку если бы он не смог получить этот индекс (поскольку ссылка на имя была бы отключена), тогда он не будет показывать это в столбце key вывода explain. Так что я определенно хочу, чтобы он использовал индекс ix_site_header_to_cleaned_text2. Чтобы убедиться, что это не сбивает с толку других, я отредактировал исходное сообщение, добавив ix_site_header_to_cleaned_text2 между ` в команду Explain.

Zoltan Fedor 06.04.2024 17:48
Ответ принят как подходящий

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

Поддержка функциональных индексов в MySQL имеет некоторые ограничения, которые вы можете не заметить, если не внимательно прочтете руководство:

https://dev.mysql.com/doc/refman/8.0/en/generated-column-index-optimizations.html

Оптимизатор может использовать индексы сгенерированных столбцов для создания планов выполнения даже при отсутствии прямых ссылок в запросах на эти столбцы по имени. Это происходит, если предложение WHERE, ORDER BY или GROUP BY относится к выражению, которое соответствует определению некоторого индексированного сгенерированного столбца.

Это означает, что он должен позволять вам использовать то же выражение, что и функциональная часть индекса (в данном случае length(cleaned_text)), и автоматически получать это значение из индекса, поэтому не нужно его пересчитывать.

Но это не работает, если вы используете это выражение в других предложениях запроса, например, в списке выбора в вашем случае или в предложении JOIN. Эта оптимизация не реализуется в других разделах, кроме тех, которые указаны в описании руководства.

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

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

Демо, протестировано на MySQL 8.0.36:

CREATE TABLE sp_files (
  id SERIAL PRIMARY KEY,
  sp_site_foreign_key INT,
  cleaned_text TEXT,
  other INT,
  length_cleaned_text INT AS (length(cleaned_text)) 
);

ALTER TABLE `sp_files`
ADD INDEX `ix_site_header_to_cleaned_text2` (`sp_site_foreign_key`, length_cleaned_text);

EXPLAIN
SELECT sp_site_foreign_key,
    count(case when length_cleaned_text > 100 then 1 else NULL END) as num1,
    count(1) as num2
FROM sp_files USE INDEX (`ix_site_header_to_cleaned_text2`)
GROUP by sp_site_foreign_key\G

Выход:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: sp_files
   partitions: NULL
         type: index
possible_keys: ix_site_header_to_cleaned_text2
          key: ix_site_header_to_cleaned_text2
      key_len: 10
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: Using index

О, вы правы, я пропустил эту часть документации MySQL!!! Я не осознавал, что столбец функционального индекса нельзя использовать в SELECT. Спасибо, идея с виртуальной колонкой просто золотая. Я только что реализовал это, и теперь EXPLAIN отображается Using index. СПАСИБО!!!

Zoltan Fedor 06.04.2024 18:25

Другие вопросы по теме