Задача заключается в выборке последних 7 топиков с содержимым первого поста, которые (топики) имеют один из указанных тегов
В таблицу (ipb_core_tags) добавил индекс по полю (tag_text)
В таблицу (ipb_topics) добавил следующие индексы (не все из них нужны, но пусть MySQL сам выбирает):
(state)
(approved, state)
(approved, state, start_date)
Индекс по полю (start_date) имеется изначально
Вот такой запрос выполняется долго:
SELECT DISTINCT `ipb_topics`.last_post AS date, `ipb_topics`.title AS title, `ipb_posts`.post AS content
FROM `ipb_topics`
LEFT JOIN `ipb_posts` ON (`ipb_topics`.topic_firstpost = `ipb_posts`.pid)
LEFT JOIN `ipb_core_tags` ON ((`ipb_topics`.tid = `ipb_core_tags`.tag_meta_id) AND (`ipb_core_tags`.tag_text IN ('Тег1', 'Тег2')) AND (`ipb_core_tags`.tag_meta_app = 'forums') AND (`ipb_core_tags`.tag_meta_area = 'topics'))
WHERE ((`ipb_topics`.approved = 1) AND (`ipb_topics`.state != 'link'))
ORDER BY `ipb_topics`.start_date DESC LIMIT 7
Согласно EXPLAIN'у:
- для выборки топиков используется индекс (approved, state, start_date)
- для выборки постов - первичный ключ таблицы постов
- для выборки тегов - индекс (tag_text)
Наблюдения:
Если убрать сортировку либо убрать оба JOIN'а (а сортировку оставить) - запрос выполняется мгновенно.
Если убрать JOIN для тегов - запрос в разы ускоряется, но от мгновенного выполнения по-прежнему далёк
Запрос может медленно выполняться из-за
а) присоединения 2 таблиц
б) или из-за медленной сортировки (сортировка всех топиков налету), наблюдаемой только при наличии присоединённых таблиц ?
Но поскольку при удалении сортировки (join'ы остаются) запрос начинает выполняться мгновенно, то причина - в б)
Вопрос:
Почему при наличии присоединённых таблиц сортировка выполняется медленно ?
Вероятно, индекс (approved, state, start_date), используемый MySQL, для сортировки таки не используется и выполняется полная сортировка всех топиков налету, после чего применяется лимит.
Если так, то почему MySQL не использует индекс (approved, state, start_date) для сортировки ? Ведь этот индекс уже содержит готовый отсортированный список топиков, удовлетворяющий всем WHERE-условиям. Т.е. нужно всего-то прочитать 7 последних строк этого индекса для требуемого ключа...
MySQL до этого не может догадаться или я чего-то не допонимаю ?
P.S. В связи с тем, что предстоит переход на IPB4, сабжевое решение является временным и не использует движок IPB
Соответственно, вопрос заключается не в том, как с помощью IPB получить сабжевые данные, а в том, как построить сабжевый запрос на чистом SQL и какие индексы для этого нужны.
Изменено пользователем cyrax_02
Рекомендованные сообщения
Создайте аккаунт или войдите в него для комментирования
Задача заключается в выборке последних 7 топиков с содержимым первого поста, которые (топики) имеют один из указанных тегов
В таблицу (ipb_core_tags) добавил индекс по полю (tag_text)
В таблицу (ipb_topics) добавил следующие индексы (не все из них нужны, но пусть MySQL сам выбирает):
(state)
(approved, state)
(approved, state, start_date)
Индекс по полю (start_date) имеется изначально
Вот такой запрос выполняется долго:
SELECT DISTINCT `ipb_topics`.last_post AS date, `ipb_topics`.title AS title, `ipb_posts`.post AS content FROM `ipb_topics` LEFT JOIN `ipb_posts` ON (`ipb_topics`.topic_firstpost = `ipb_posts`.pid) LEFT JOIN `ipb_core_tags` ON ((`ipb_topics`.tid = `ipb_core_tags`.tag_meta_id) AND (`ipb_core_tags`.tag_text IN ('Тег1', 'Тег2')) AND (`ipb_core_tags`.tag_meta_app = 'forums') AND (`ipb_core_tags`.tag_meta_area = 'topics')) WHERE ((`ipb_topics`.approved = 1) AND (`ipb_topics`.state != 'link')) ORDER BY `ipb_topics`.start_date DESC LIMIT 7Согласно EXPLAIN'у:
- для выборки топиков используется индекс (approved, state, start_date)
- для выборки постов - первичный ключ таблицы постов
- для выборки тегов - индекс (tag_text)
Наблюдения:
Если убрать сортировку либо убрать оба JOIN'а (а сортировку оставить) - запрос выполняется мгновенно.
Если убрать JOIN для тегов - запрос в разы ускоряется, но от мгновенного выполнения по-прежнему далёк
Запрос может медленно выполняться из-за
а) присоединения 2 таблиц
б) или из-за медленной сортировки (сортировка всех топиков налету), наблюдаемой только при наличии присоединённых таблиц ?
Но поскольку при удалении сортировки (join'ы остаются) запрос начинает выполняться мгновенно, то причина - в б)
Вопрос:
Почему при наличии присоединённых таблиц сортировка выполняется медленно ?
Вероятно, индекс (approved, state, start_date), используемый MySQL, для сортировки таки не используется и выполняется полная сортировка всех топиков налету, после чего применяется лимит.
Если так, то почему MySQL не использует индекс (approved, state, start_date) для сортировки ? Ведь этот индекс уже содержит готовый отсортированный список топиков, удовлетворяющий всем WHERE-условиям. Т.е. нужно всего-то прочитать 7 последних строк этого индекса для требуемого ключа...
MySQL до этого не может догадаться или я чего-то не допонимаю ?
-----------------------------------------------------------------------------------------------------------------------------------------------
P.S. В связи с тем, что предстоит переход на IPB4, сабжевое решение является временным и не использует движок IPB
Соответственно, вопрос заключается не в том, как с помощью IPB получить сабжевые данные, а в том, как построить сабжевый запрос на чистом SQL и какие индексы для этого нужны.
Изменено пользователем cyrax_02