2010-07-26 5 views
3

Никогда не видел этого раньше. Выполняя тот же запрос, 1 заставляет индекс. Без индекса результаты неверны (в неправильном порядке), с индексом результаты находятся в правильном порядке. Только проблема с использованием индекса заключается в том, что по какой-то причине он медленнее. Индекс на comment_id и user_idс индексом, возвращает другой результат

без индекса:

SELECT DISTINCT topic_id FROM comments 
WHERE user_id=9384 
AND (status = 1 or status = 0) 
ORDER BY comment_id DESC LIMIT 15 

с индексом:

SELECT DISTINCT topic_id FROM comments force index(index_comment_user) 
WHERE user_id=9384 
AND (status = 1 or status = 0) 
ORDER BY comment_id DESC LIMIT 15 

Любые идеи? Я действительно хочу получить правильный порядок, не замедляя запрос. Я бы сделал так, чтобы индекс сделал это.

Вот структура SQL.

CREATE TABLE `db`.`comments` (
    `comment_id` int(10) unsigned NOT NULL auto_increment, 
    `old_comments_id` mediumint(8) unsigned default NULL, 
    `user_id` mediumint(8) unsigned default NULL, 
    `content` text character set latin1, 
    `status` tinyint(3) unsigned default NULL, 
    `added_date` datetime default NULL, 
    `category_id` tinyint(3) unsigned default NULL, 
    `helpful` tinyint(3) unsigned default NULL, 
    `modified_date` datetime default NULL, 
    `topic_id` mediumint(8) unsigned default NULL, 
    `last_mod_user_id` mediumint(8) unsigned default NULL, 
    PRIMARY KEY USING BTREE (`comment_id`), 
    KEY `Index_user_id` (`user_id`), 
    KEY `Index_added_date` (`added_date`), 
    KEY `Index_comments_status` USING BTREE (`status`), 
    KEY `Index_user_activity` USING BTREE (`comment_id`,`user_id`), 
    KEY `Index_user_activity2` USING BTREE (`user_id`,`topic_id`), 
    KEY `Index_question_id` USING BTREE (`topic_id`,`status`), 
    KEY `Index_user_activity3` (`user_id`,`status`,`topic_id`,`comment_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=2040237 DEFAULT CHARSET=utf8; 
+0

Является ли MySQL требователен порядка столбцов в индексе - то есть, если вы создаете индекс на user_id , column_id вместо этого поможет? – Rup

+0

Просьба также показать точное определение таблицы. – Tomalak

+0

sql table structure добавлено – David

ответ

2

Ваше использование DISTINCT вместе с ORDER BY на колонке, которую вы не выбираете, вызовет проблемы. Попробуйте использовать GROUP BY вместо:

SELECT topic_id, MAX(comment_id) AS comment_id 
FROM comments 
WHERE user_id=9384 AND status IN (0, 1) 
GROUP BY topic_id 
ORDER BY comment_id DESC 
LIMIT 15 

Вам не нужно форсировать индекс. Просто добавьте правильный индекс, и он должен использоваться автоматически. Возможно, вы захотите попробовать различные комбинации и упорядочить столбцы в индексе, чтобы увидеть, какая из них лучше всего работает.

+0

этот запрос в порядке, однако.Он не считает, что я хочу получить самые последние комментарии. Таким образом, мне нужен заказ comment_id, который, чем бросает файл, который не является хорошим. – David

+0

«Он не считает, что я хочу получить самые последние комментарии».: У меня был min вместо max (я не заметил DESC). Теперь это исправлено. –

+0

Это не исключает проблему. Мне все еще нужен порядок. Поскольку вам нужно выбрать темы с идентификатором MAX comment, а не только первым 15. Таким образом, ORDER BY comment_id не делает этого, но fileort происходит. – David

0

The manual says

Если таблица имеет индекс нескольких столбцов, любой крайний левый префикс индекса может использоваться оптимизатором для поиска строк. Например, если у вас есть индекс с тремя столбцами (col1, col2, col3), у вас есть индексированные возможности поиска в (col1), (col1, col2) и (col1, col2, col3).

то я думаю, что вам нужен индекс user_id, column_id для запроса - это не звучит, как MySQL может использовать column_id, user_id. Чтобы проверить это, вы должны запустить EXPLAIN SELECT по обоим запросам.

Почему это не так с другим индексом, который я не знаю, извините.

0

Просьба представить результат

EXPLAIN SELECT topic_id, MAX(comment_id) AS commentId 
FROM comments 
WHERE user_id=9384 AND status IN (0, 1) 
GROUP BY topic_id 
ORDER BY commentId DESC 
LIMIT 15 

Я хотел бы знать, если это имеет значение, если псевдоним для MAX (comment_id) одно и то же имя с колонкой или нет. Это неоднозначно, как вы можете определить, использует ли mysql столбец или функцию агрегата для сортировки?

0

Это общий «Макс в группе» проблемы, и обычно она решается так:

SELECT 
    comment.user_id, 
    comment.topic_id, 
    comment.comment_id 
FROM 
    comment 
    INNER JOIN (
     SELECT user_id, topic_id, MAX(comment_id) AS comment_id 
     FROM comments 
    GROUP BY user_id, topic_id 
) AS max ON max.comment_id = comment.comment_id 
WHERE 
    comment.user_id = 9384 
    AND comment.status IN (1, 0) 
ORDER BY 
    comment.comment_id DESC