MySQL: Индекс при присоединении к таблицам не используется (вопрос оптимизации производительности)
-
16-10-2019 - |
Вопрос
Мне нужно оптимизировать следующий запрос:
SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM blogposts
JOIN articles ON articles.blogpost_id = blogposts.id
WHERE blogposts.deleted = 0
AND blogposts.title LIKE '%{de}%'
AND blogposts.visible = 1
AND blogposts.date_published <= NOW()
ORDER BY blogposts.date_created DESC
LIMIT 0 , 50
Объясните, Select дает мне следующий результат:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE articles ALL blogpost_id NULL NULL NULL 6915 Using temporary; Using filesort
1 SIMPLE blogposts eq_ref PRIMARY PRIMARY 4 articles.blogpost_id 1 Using where
Почему это сначала берет статьи, а затем в блог -посты? Это потому, что в блогах есть больше записей? И как я могу улучшить запрос, чтобы статьяпост могла использовать индекс?
Обновлять:Индекс установлен на blogposts.date_created. Удаление блога.
Когда я удаляю "Статьи. ID как статья«Он может использовать индекс blogpost_id на статьях ... звучит странно для меня, кто -то знает почему? (Потому что мне это действительно нужно ..)
А Новое объяснение Похоже:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE articles index blogpost_id blogpost_id 4 NULL 6915 Using index; Using temporary; Using filesort
1 SIMPLE blogposts eq_ref PRIMARY PRIMARY 4 articles.blogpost_id 1 Using where
Решение
Я поближе посмотрел на запрос, и вы сможете перепроектировать его. Вот что я имею в виду:
Предел 0,50 часть запроса, по -видимому, становятся занятыми в последнем запросе.
Вы можете улучшить планировку запроса, выполнив следующее:
Шаг 1) Создайте встроенный запрос, чтобы собрать только ключи. В этом случае удостоверение личности для блога.
Шаг 2) Навязать в любом случае, порядок и группа по пунктам по встроенным запросу, приносящим ключи.
Шаг 3) Имейте поговорку о предельном пункте как последний шаг в создании встроенного запроса.
Шаг 4) Присоединяйтесь к встроенному запросу с таблицей блогпост
Шаг 5) Присоединяйтесь к этому новому Temptalbable Blog Plogable с таблицей статей.
Шаги 1-3 предназначены для создания соблазности с ровно 50 строк и включить идентификатор блога. Затем выполните все соединения мертвых последних.
С этими шагами, применяемыми к вашему первоначальному запросу, вы должны иметь это:
SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
SELECT B.*
FROM
(
SELECT id FROM blogposts
WHERE date_published <= NOW()
AND deleted = 0 AND visible = 1
AND title LIKE '%{de}%'
ORDER BY date_created DESC
LIMIT 0,50
) A
INNER JOIN blogposts B USING (id)
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id;
Поскольку вы отредактировали вопрос и заявили, что вы удалите, теперь ваш запрос должен больше похож на это:
SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
SELECT B.*
FROM
(
SELECT id FROM blogposts
WHERE date_published <= NOW()
AND deleted = 0 AND visible = 1
ORDER BY date_created DESC
LIMIT 0,50
) A
INNER JOIN blogposts B USING (id)
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id;
Во фразе [вещи опущены], если вам ничего не нужно из блога, кроме ключей, то ваш запрос должен выглядеть следующим образом:
SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
SELECT id FROM blogposts
WHERE date_published <= NOW()
AND deleted = 0 AND visible = 1
ORDER BY date_created DESC
LIMIT 0,50
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id;
ПРЕДОСТЕРЕЖЕНИЕ
Убедитесь, что вы создаете индекс, который включает в себя удаленные, видимые и дату дата
ALTER TABLE blogposts ADD INDEX deleted_visible_date_created (deleted,visible,date_created);
Попробуй !!!
Другие советы
Ваше место, где blogposts.title LIKE '%{de}%'
приведет к полному сканированию на столе на Сообщения в блоге стол. Скорее всего, фигуры MySQL Сканирование 6915 статей более эффективно.
Что касается его улучшения, вы можете добавить индекс на Сообщения в блоге с использованием date_created
или же date_published
и добавьте диапазон к условию, где иное, чем <= сейчас ())
И blogposts.title like '%{de}%' - бесполезно для оптимизации (ведущая дикая карта)
Где blogposts.deleted = 0 и blogposts.visible = 1 - yuck: если их нельзя показывать, вытащите их из таблицы.
И blogposts.date_published <= now () Заказ Blogposts.date_created Decs Limit 0, 50 - что приводит к необходимости индекса (date_published) (однако, подобные и флаги могут предотвратить использование этого индекса.)
Пожалуйста, предоставьте таблицу Show Create ...; Показать статус таблицы ...;
Большое спасибо :)
Я попробовал и узнал, что на самом деле ваш последний комментарий о индексе был тем, что мне было нужно. Иногда это просто небольшое улучшение, которое необходимо ...;) Сравнение:
Старый запрос:
SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM blogposts
JOIN articles ON articles.blogpost_id = blogposts.id
WHERE blogposts.deleted = 0
AND blogposts.title LIKE '%{de}%'
AND blogposts.visible = 1
AND blogposts.date_published <= NOW()
ORDER BY blogposts.date_created DESC
LIMIT 0 , 50
Новый запрос:
SELECT /* [things omitted] */ articles.blogpost_id, articles.id AS articleid
FROM
(
SELECT B.*
FROM
(
SELECT id FROM blogposts
WHERE date_published <= NOW()
AND deleted = 0 AND visible = 1
AND title LIKE '%{de}%'
ORDER BY date_created DESC
LIMIT 0,50
) A
INNER JOIN blogposts B USING (id)
) blogposts
INNER JOIN articles
ON blogposts.id = articles.blogpost_id
Теперь без упомянутого индекса:
Старый объяснение результат:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE articles ALL blogpost_id NULL NULL NULL 6915 Using temporary; Using filesort
1 SIMPLE blogposts eq_ref PRIMARY PRIMARY 4 articles.blogpost_id 1 Using where
Новое объяснение результата:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 50
1 PRIMARY articles ref blogposts_id blogposts_id 4 blogposts.id 1
2 DERIVED <derived3> ALL NULL NULL NULL NULL 50
2 DERIVED B eq_ref PRIMARY PRIMARY 4 A.id 1
3 DERIVED blogposts ALL deleted,visible,date_published deleted 1 28198 Using filesort
Объясните результат с указанием старого запроса:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE blogposts ref PRIMARY,deleted,visible,date_published,deleted_vis... deleted_visible_date_created 2 const,const 27771 Using where
1 SIMPLE articles ref blogposts_id blogposts_id 4 db.blogposts.id 1
Объясните результат с указанием нового запроса:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 50
1 PRIMARY articles ref blogposts_id blogposts_id 4 blogposts.id 1
2 DERIVED <derived3> ALL NULL NULL NULL NULL 50
2 DERIVED B eq_ref PRIMARY PRIMARY 4 A.id 1
3 DERIVED blogposts ref deleted,visible,date_published,deleted_visible_dat... deleted_visible_date_created 2 27771 Using where
Скорость на старом запросе без/с индексом: 0.1835/0.0037
Скорость на новом запросе без/с индексом: 0.1883/0.0035
Таким образом, из -за справедливой разницы между старым/новым запросом я предпочитаю использовать старый запрос, но с индексом. Но я буду помнить об этом, как будто когда -нибудь старый запрос слишком медленный :)
Что было бы интересно для меня, так это знать, как у вас есть идея установить такой индекс? Я думаю, что, опубликовав этот вопрос, я также попробовал с deleted_visible, но вместо date_created я использовал date_publised (как это в том, где оказалось) ...
Спасибо :)
Обновление Rolandomysqldba 2011-05-19 13:03
То, что отдало его мне, было то, где и порядок по пунктам.
В пункте «Где удален» (0) и видимым (1) являются статические значения. В предложении «Заказ по поводу», дата_1Created была похожа на движущуюся цель среди всех строк с удаленным = 0 и видимым = 1. Итак, я сначала положил статические переменные перед индексом, затем движущаяся цель в индексе Обычно это является частью основного принципа рефакторирования заявлений SQL. Вам нужны индексы, которые будут поддерживать ваше место, группируются и заказывают положения.