MySQL ORDER BY DESC很快但ASC很慢

时间:2010-05-22 01:29:40

标签: mysql performance

我对这个完全感到难过。出于某种原因,当我通过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;

两个查询的EXPLAIN都相同。

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 个答案:

答案 0 :(得分:5)

你的索引是desc排序所以当你要求升序时,它需要做更多的工作才能按顺序恢复它

答案 1 :(得分:3)

您可以先获取数据集,然后再订购。

这样的东西
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;

首先应该使用索引来查找满足“where”语句的所有记录,并且将对它们进行排序。但订单将在较小的集合中执行。试一试然后告诉我们。

最诚挚的问候。

答案 2 :(得分:1)

我不建议你在桌子上创建另一个索引;每次插入或删除行时,都需要更新表上的每个索引,从而减慢INSERT次查询速度。

该指数绝对会减缓它的速度。也许你可以尝试IGNORE - 它:

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,您可以尝试以下操作:

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;

答案 3 :(得分:0)

如何翻转WHERE条件?

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;

答案 4 :(得分:0)

您希望跨(feed_id,已发布)添加索引:

ALTER TABLE posts ADD INDEX (feed_id, published)

这将使此查询运行得最好,并且您不需要使用USE INDEX强制使用特定索引。