Справка по индексации таблиц MySQL при использовании GROUP BY в запросе - PullRequest
0 голосов
/ 10 января 2011

Спасибо за внимание.

Существует две таблицы INNODB:

Таблица авторы

id        INT
nickname  VARCHAR(50) 
status    ENUM('active', 'blocked')
about     TEXT

Таблица книги

author_id  INT
title      VARCHAR(150)

Я выполняю запрос к этим таблицам, чтобы получить каждого автора и количество книг, которые у него есть:

SELECT a. * , COUNT( b.id ) AS book_count
FROM authors AS a, books AS b
WHERE a.status != 'blocked'
AND b.author_id = a.id
GROUP BY a.id
ORDER BY a.nickname

Этот запрос очень медленный (занимает около6 секунд, чтобы выполнить).У меня есть индекс для books.author_id, и он отлично работает, но я не знаю, как создать индекс для таблицы authors, чтобы этот запрос мог его использовать.

Вот как выглядит текущий EXPLAIN:

id   select_type   table    type    possible_keys               key            key_len   ref     rows    Extra
1    SIMPLE        a        ALL     PRIMARY,id_status_nickname  NULL           NULL      NULL    3305    Using where; Using temporary; Using filesort
1    SIMPLE        b        ref     key_author_id               key_author_id  5         a.id    2       Using where; Using index

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

IБуду признателен за любую помощь и советы по этому вопросу - какой должна быть структура индекса, чтобы MySQL мог использовать его?

Редактировать

Я пробовал:

(id, status, nickname)
(status, nickname)

Оба привели к одной и той же ситуации.

Ответы [ 2 ]

3 голосов
/ 10 января 2011

Я предполагаю, что id_status_nickname является составным индексом (id, status, псевдоним). В своем запросе вы фильтруете строки, говоря a.status! = Заблокирован. Это имеет следующие проблемы:

  1. У вас нет индекса, который можно использовать для этого. (id, status, псевдоним) нельзя использовать, потому что status не является префиксом этого индекса
  2. Если у вас есть индекс состояния, его нельзя использовать при использовании! =. Вы должны изменить это на status = 'active'
  3. Кроме того, если в качестве поля перечисления указано только два значения, то количество элементов будет низким. Таким образом, mysql может вообще не использовать индекс.

Вы можете попробовать это: создать индекс как (status, id, псевдоним) и использовать status = 'active'. Я предполагаю, что, поскольку вы используете '=', а статус является префиксом индекса, он должен выбрать этот индекс и затем использовать его для группировки по группам, а затем упорядочить по.

UPDATE: Похоже, невозможно избежать сортировки файлов, если в предложении WHERE нет поля, используемого в ORDER BY.

0 голосов
/ 10 января 2011

Я бы попробовал индекс на (статус, никнейм).Это должно избавить от необходимости «Использование файловой сортировки».

...