MySQL: Индекс при присоединении к таблицам не используется (вопрос оптимизации производительности)

dba.stackexchange https://dba.stackexchange.com/questions/872

Вопрос

Мне нужно оптимизировать следующий запрос:

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. Вам нужны индексы, которые будут поддерживать ваше место, группируются и заказывают положения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top