Индексы MySQL: почему индекс по нескольким столбцам работает хуже, чем индекс по одному столбцу? - PullRequest
0 голосов
/ 31 января 2019

Я изучаю индексы и решил попробовать эксперимент с базой данных MySQL Sakila.У меня есть следующий запрос:

SELECT title, release_year
FROM film
WHERE release_year < 2010
AND rating = 'R';

Это первый индекс, который я пробовал:

CREATE INDEX idx_releaseYear ON film(rating);

Когда я запустил свой запрос, MySQL EXPLAIN вернул это:

enter image description here

РЕДАКТИРОВАТЬ: Моя интерпретация этих результатов: MySQL использует индекс (отсортированный по рейтингу), чтобы быстро найти все фильмы с рейтингом «R», а затем проверяет год выпуска каждой строкивозвращается индексом.

Далее я создал индекс по рейтингу и release_year:

CREATE INDEX idx_releaseYear ON film(rating, release_year);

Когда я запустил свой запрос, MySQL EXPLAIN вернул это:

enter image description here

РЕДАКТИРОВАТЬ: Мои ожидания: MySQL будет использовать индекс (отсортированный по рейтингу, затем release_year), чтобы быстро найти все R-рейтинговые фильмы и release_years <2010, и использовать толькотаблица фильмов для получения названий фильмов из строк, возвращаемых индексом.Несмотря на то, что все фильмы в базе данных имеют одинаковый release_year, я думал, что сортировка индекса по рейтингу, а затем год выпуска будет работать лучше (или, по крайней мере, так же, используя только первый столбец индекса), как первый запрос, так как в первомзапрос должен был проверить годы выпуска в случайном порядке. </p>

Почему первый индекс с одним столбцом работает лучше, чем второй индекс с несколькими столбцами?Я думал, что они будут выполнять, по крайней мере, то же самое, так как рейтинг указан первым.

Есть одна вещь, о которой вы должны знать: Все фильмы в базе данных имеют год выпуска 2006.

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Ваши «ожидания» верны.EXPLAIN неточно;не доверяйте этому слишком далеко.

WHERE release_year < 2010
  AND rating = 'R'

(обычно) лучше всего оптимизируется с помощью

INDEX(rating,   -- first, because it is tested with '='
      release_year)   -- last, because it is a range.

Если вы можете позволить себе запустить его в обоих направлениях, просмотр SESSION STATUS LIKE 'Handler%' дает вам точнуюпросматривать строки читать (и, возможно, записать во временные таблицы).Я обсуждаю эту технику здесь .В этом блоге также объясняется, что составной индекс является лучшим.

Исключения из этого списка являются лучшими:

  • Возможно, статистика говорит, что использование индекса не стоит усилий;может быть, лучше просто сканировать таблицу.
  • Возможно, было бы лучше расширить ее, чтобы она "покрывала".(Не для рассматриваемого запроса.)
  • Возможно, PRIMARY KEY должна быть этой парой столбцов или, по крайней мере, начинаться с них.Это позволяет избежать отказов между индексом BTree и Data BTree.

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

Примечание: если вы выберете ORDER BY release_year LIMIT 5, составной индекс действительно сияет.Это связано с тем, что индекс можно использовать для всех WHERE, всех ORDER BY, получить значение LIMIT и коснуться только 5 строк.Почти любой другой сценарий должен собрать множество строк во временной таблице, отсортировать их, а затем очистить 5 строк.

0 голосов
/ 31 января 2019

Это слишком долго для комментария.

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

Индексы не предназначены для данных такого размера.Они предназначены для ускорения выполнения запросов к гораздо большим наборам данных.Есть некоторые накладные расходы на использование индекса.Например, MySQL должен загрузить и страницы данных, и страницы индекса, чтобы выполнить запрос.Вы, вероятно, не получите никакой экономии, уменьшив количество читаемых страниц.

Мораль проста.Не судите о производительности по очень маленьким запросам.Зачастую индексы в этих случаях не нужны, поскольку они имеют дополнительные издержки.

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