MySQL ORDER BY DESC быстрый, но ASC очень медленный - PullRequest
12 голосов
/ 22 мая 2010

Я полностью озадачен этим. По какой-то причине, когда я сортирую этот запрос по DESC, он супер быстрый, но если сортировать по ASC, он очень медленный.

Это займет около 150 миллисекунд:

SELECT posts.id
FROM posts USE INDEX (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
ORDER BY posts.published DESC
LIMIT 0, 50;

Это займет около 32 секунд:

SELECT posts.id
FROM posts USE INDEX (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
ORDER BY posts.published ASC
LIMIT 0, 50;

Объяснение одинаково для обоих запросов.

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  posts   index   NULL    published   5   NULL    50  Using where

Я отследил его до "ИСПОЛЬЗОВАТЬ ИНДЕКС (опубликовано)". Если я возьму это, это - та же самая производительность оба пути. Но EXPLAIN показывает, что запрос в целом менее эффективен.

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  posts   range   feed_id feed_id 4   \N  759 Using where; Using filesort

А вот и таблица.

CREATE TABLE `posts` (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `feed_id` int(11) NOT NULL,
  `post_url` varchar(255) NOT NULL,
  `title` varchar(255) NOT NULL,
  `content` blob,
  `author` varchar(255) DEFAULT NULL,
  `published` int(12) DEFAULT NULL,
  `updated` datetime NOT NULL,
  `created` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `post_url` (`post_url`,`feed_id`),
  KEY `feed_id` (`feed_id`),
  KEY `published` (`published`)
) ENGINE=InnoDB AUTO_INCREMENT=196530 DEFAULT CHARSET=latin1;

Есть ли исправление для этого? Спасибо!

Ответы [ 5 ]

5 голосов
/ 22 мая 2010

Ваш индекс отсортирован desc, поэтому, когда вы запрашиваете возрастание, ему нужно проделать гораздо больше работы, чтобы вернуть его в этом порядке

2 голосов
/ 15 июня 2010

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

Что-то вроде

SELECT posts.id FROM (
SELECT posts.id
FROM posts USE INDEX (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
LIMIT 0, 50
)
order by postS.id ASC;

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

С наилучшими пожеланиями.

1 голос
/ 22 мая 2010

Я бы не советовал вам создавать другой индекс для таблицы;каждый раз, когда строка вставляется или удаляется, каждый индекс в таблице необходимо обновлять, замедляя INSERT запросов.

Индекс определенно замедляет его.Возможно, вы могли бы попробовать IGNORE -ing it:

SELECT posts.id
FROM posts IGNORE INDEX (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
ORDER BY posts.published ASC
LIMIT 0, 50;

Или, так как поле уже KEY ed, вы можете попробовать следующее:

SELECT posts.id
FROM posts USE KEY (published)
WHERE posts.feed_id IN ( 4953,622,1,1852,4952,76,623,624,10 )
ORDER BY posts.published ASC
LIMIT 0, 50;
0 голосов
/ 22 мая 2010

Вы хотите добавить индекс по (feed_id, опубликовано):

ALTER TABLE posts ADD INDEX (feed_id, published)

Это сделает этот запрос наиболее эффективным, и вам не нужно будет принудительно указывать определенный индекс с помощью USE INDEX.

0 голосов
/ 22 мая 2010

Как насчет переключения условия ГДЕ?

SELECT posts.id
FROM posts USE INDEX (published)
WHERE posts.feed_id IN ( 10,624,623,76,4952,1852,622,4953 )
ORDER BY posts.published DESC;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...