Настоящая проблема в том, что нет необходимости оптимизировать MySQL объяснение. Обычно существует запрос (или несколько запросов), который вы хотите повысить, и EXPLAIN
- это способ узнать, произойдет ли выполнение запроса так, как вы ожидаете.
То есть вам необходимо понять, как должен выглядеть план выполнения и почему, и сравнить его с результатами команды EXPLAIN
. Чтобы понять, как план будет выглядеть, вы должны понять как работают индексы в MySQL .
Между тем, ваш запрос сложный, поскольку для эффективного использования индекса он имеет некоторые ограничения: а) одновременное упорядочение по полю из одной таблицы и б) поиск последнего элемента в каждой группе от другого (последнее само по себе является непростой задачей). Поскольку ваша база данных довольно мала, вам повезло, что ваш текущий запрос довольно быстрый (хотя вы считаете его медленным).
Я бы немного переписал запрос (я предполагаю, что для каждого вида есть хотя бы одно фото):
SELECT
specie.id, specie.commonname, specie.block_description,
maximage.title, maximage.karma,
imagefile.file_name, imagefile.width, imagefile.height, imagefile.transferred
FROM (
SELECT s.id,
(SELECT i.id
FROM specie_map sm
JOIN image i ON sm.image_id = i.id
WHERE sm.specie_id = s.id
ORDER BY i.karma DESC
LIMIT 1) as image_id
FROM specie s
ORDER BY s.commonname
LIMIT 0, 24
) as ids
JOIN specie
ON ids.id = specie.id
JOIN image as maximage
ON maximage.id = ids.image_id
JOIN imagefile
ON imagefile.image_id = ids.image_id AND imagefile.type = 'small';
Вам понадобятся следующие индексы:
(commonname)
на specie
- композит
(specie_id, image_id)
на specie_map
- композит
(id, karma)
на image
- композит
(image_id, type)
на imagefile
Пейджинг теперь должен происходить внутри подзапроса.
Идея состоит в том, чтобы делать сложные вычисления в подзапросе, который работает только с идентификаторами, и объединять оставшиеся данные сверху. Данные будут упорядочены в порядке результатов подзапроса.