Помогите оптимизировать MySQL SELECT с помощью ORDER BY - PullRequest
2 голосов
/ 13 июля 2011

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

  1. forum_id_index
  2. other_forum_id_index
  3. forum_id_on_other_forum_id_index => [forum_id, other_forum_id]

Запрос:

SELECT `topics.*` 
FROM `topics` 
WHERE (table.forum_id = ? OR table.other_forum_id = ?) 
ORDER by sticky, replied_at DESC LIMIT 25

Я пытался добавить индексы для следующего:

  1. липкий
  2. replied_at
  3. [sticky, replied_at]
  4. [forum_id, other_forum_id, sticky, replied_at]
  5. [sticky, replied_at, forum_id, other_forum_id]

Это для форума, пытающегося получить 25 лучших тем на форуме, но помещающих sticky тем (sticky - это двоичное поле для sticky / nonsticky) вверху.

Я прочитал почти все, что могу, об оптимизации ORDER BY, но не повезло. Это на MySQL 5.1, INNODB. Любая помощь будет принята с благодарностью.

редактирует

Как и просили в комментариях (извините, если я делаю это неправильно - новость в публикации на SU). Результаты EXPLAIN в настоящее время:

id = 1

select_type = SIMPLE

таблица = темы

type = index_merge

возможных_кликов = index_topics_on_forum_id, index_topics_on_sticky_and_replied_at, index_topics_on_forum_id_and_replied_at, index_topics_on_video_forum_id, index_forum_id_on_video_forum_id,

keys = index_topics_on_forum_id, index_topics_on_video_forum_id

key_len = 5,5

ref = NULL

строк = 13584

Extra = Использование объединения (index_topics_on_forum_id, index_topics_on_video_forum_id); Используя где; Использование filesort

ПОКАЗАТЬ ИНДЕКСЫ ИЗ ТЕМОВ ВОЗВРАЩАЕТСЯ https://gist.github.com/1079454 - Не удалось получить форматирование, чтобы хорошо отображаться здесь.

РЕДАКТИРОВАТЬ 2

SELECT `topics`.*
FROM `topics`
WHERE topics.forum_id=4
ORDER BY sticky desc, replied_at DESC

Работает невероятно быстро (1,4 мс). То же относится и к запросу, когда я изменяю themes.forum_id на themes.video_forum_id - только не тогда, когда они есть в запросе с помощью или.

Ответы [ 4 ]

1 голос
/ 13 июля 2011

Я думаю, что это должно быть очень быстро.

Индексы:

ALTER TABLE `topics` 
    ADD INDEX `forum` (`forum_id` ASC, `sticky` ASC, `replied_at` DESC), 
    ADD INDEX `other_forum` (`other_forum_id` ASC, `sticky` ASC, `replied_at` DESC);

Запрос:

(
    SELECT `topics.*` 
    FROM `topics` USE INDEX (`forum`)
    WHERE `topics`.forum_id = ?
    ORDER by sticky, replied_at DESC 
    LIMIT 25
) UNION (
    SELECT `topics.*` 
    FROM `topics` USE INDEX (`other_forum`)
    WHERE `topics`.other_forum_id = ?
    ORDER by sticky, replied_at DESC 
    LIMIT 25
)
ORDER by sticky, replied_at DESC 
LIMIT 25
0 голосов
/ 13 июля 2011

Вы можете попробовать 2 вещи:

  • Один, с индексами на:

    • (forum_id, sticky, replied_at)
    • (other_forum_id, sticky, replied_at)

либо с вашим исходным запросом, либо предложением Каролиса, либо

  • Два, с индексами на:

    • (forum_id)
    • (other_forum_id)
    • (sticky, replied_at)
0 голосов
/ 13 июля 2011

Используйте команду MySQL EXPLAIN , чтобы узнать о стоимости, связанной с вашим запросом:

EXPLAIN SELECT ...

Просмотрите таблицы сканирования, которые, вероятно, будут дорогостоящими.

Кроме того, MySQL может использовать или не использовать индекс.Это зависит исключительно от того, как оптимизатор запросов понимает ваш запрос.

FORCE INDEX может помочь, поскольку эта опция сообщает MySQL, что сканирование таблиц будет обходиться очень дорого.Посмотрите здесь .

0 голосов
/ 13 июля 2011

Попробуйте индексы [forum_id, sticky, replied_at desc] и [other_forum_id, sticky, replied_at desc]

Вы также можете попробовать сформулировать запрос как объединение:

    SELECT `topics.*` FROM `topics` WHERE (table.forum_id = ?)
UNION
SELECT `topics.*` FROM `topics` WHERE (table.other_forum_id = ?)
 ORDER by sticky, replied_at DESC LIMIT 25
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...