Как я могу оптимизировать этот запутанно медленный запрос в MySQL? - PullRequest
4 голосов
/ 26 октября 2010

У меня есть таблица постов в блоге, каждый с внешним ключом обратно к его автору. В этой таблице <15 000 записей. Этот запрос сканирует более 19 000 строк (на <code>EXPLAIN), требует файловой сортировки (что может быть обычным поведением MySQL) и занимает более 400 мс, чтобы вернуть 5 строк. возможно, из-за сложного WHERE, используемого для проверки, действительно ли элемент опубликован.

Dearest Stack Overflow, как я могу обработать этот запрос под контролем?

Примечание: хотя этот критерий может быть упрощен, все условия обязательны.

SELECT      `blog_post.id`, 
            `blog_post.title`,
            `blog_post.author_id`,
            `blog_post.has_been_fact_checked`,
            `blog_post.published_date`,
            `blog_post.ordering`,
            `auth_user.username`,
            `auth_user.email`
FROM        `blog_post` 
INNER JOIN  `auth_user` 
ON          (`blog_post`.`author_id` = `auth_user`.`id`) 
WHERE       (`blog_post`.`is_approved` = True  AND 
             `blog_post`.`has_been_fact_checked` = True  AND 
             `blog_post`.`published_date` IS NOT NULL AND 
             `blog_post`.`published_date` <= '2010-10-25 22:40:05' ) 
ORDER BY    `blog_post`.`published_date` DESC, 
            `blog_post`.`ordering` ASC, 
            `blog_post`.`id` DESC 
LIMIT 5

Помимо PK у меня есть следующие индексы в таблице:

idx_published_blog_post -> blog_post(is_approved, has_been_fact_checked, published_date)
idx_pub_date -> blog_post(published_date)

Вывод EXPLAIN выглядит следующим образом:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: blog_post
         type: ref
possible_keys: blog_post_author_id,idx_published_blog_post,idx_pub_date
          key: idx_published_blog_post
      key_len: 4
          ref: const,const
         rows: 19856
        Extra: Using where; Using filesort
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: auth_user
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: blog.blog_post.author_id
         rows: 1
        Extra: Using index
2 rows in set (0.00 sec)

Примечание: 2010-10-25 22:40:05 - это просто дата, сгенерированная кодом, который выполняет этот запрос.

Большое спасибо за любую помощь!

Ответы [ 3 ]

5 голосов
/ 27 октября 2010

MySQL не поддерживает предложения ASC/DESC в индексах.

Вам потребуется создать отдельный столбец с именем reverse_ordering и установить его значение на -ordering (при условии, что ordering являетсячисловое значение)

Затем вы можете создать следующий индекс:

CREATE INDEX ix_blogpost_a_c_p_ro_id ON blog_post (is_approved, has_been_fact_checked, published_date, reverse_ordering, id)

и переписать свой запрос:

SELECT      `blog_post.id`, 
            `blog_post.title`,
            `blog_post.author_id`,
            `blog_post.has_been_fact_checked`,
            `blog_post.published_date`,
            `blog_post.ordering`,
            `auth_user.username`,
            `auth_user.email`
FROM        `blog_post` 
INNER JOIN  `auth_user` 
ON          `blog_post`.`author_id` = `auth_user`.`id`
WHERE       `blog_post`.`is_approved` = 1 AND 
            `blog_post`.`has_been_fact_checked` = 1 AND 
            `blog_post`.`published_date` <= '2010-10-25 22:40:05'
ORDER BY    `blog_post`.`published_date` DESC, 
            `blog_post`.`reverse_ordering` DESC, 
            `blog_post`.`id` DESC 
LIMIT 5

Вы можете избавиться от проверки IS NULL,поскольку условие неравенства подразумевает его.

Обновление:

Вы также можете прочитать эту статью:

0 голосов
/ 27 октября 2010

Мне кажется, что сортировка файлов может убивать скорость. Если вы можете добавить поля ORDER BY в используемый индекс, вы можете получить увеличение скорости. Попробуйте изменить:

idx_published_blog_post -> blog_post (is_approved, has_been_fact_checked, опубликовано_дата)

до

idx_published_blog_post -> blog_post (is_approved, has_been_fact_checked, publ_date DESC, заказ ASC, id DESC)

Пара мыслей: при каких обстоятельствах у вас есть нулевое значение ключ_публикации, поиск в диапазоне дат может быть быстрее? Кроме того, ключ публикации_даты, по-видимому, является полем даты и времени, поэтому при сортировке у вас действительно есть сообщения, которые могут требовать каждую секунду для других полей сортировки?

0 голосов
/ 26 октября 2010

Создайте представление «blog_post» со всеми условиями, которые вы применили в запросе (предложение where), и выполните соединение «auth_user» напрямую с этим представлением.

Не стесняйтесь спрашивать, если не ясно:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...