我有一个非常简单的查询(表类型InnoDb)和EXPLAIN
说MySQL必须做一个额外的传递来找出如何按排序顺序检索行。
SELECT * FROM `comments`
WHERE (commentable_id = 1976)
ORDER BY created_at desc LIMIT 0, 5
准确解释输出:
table select_type type extra possible_keys key key length ref rows
comments simple ref using where; using filesort common_lookups common_lookups 5 const 89
commentable_id被编入索引。评论没有任何技巧,只是一个内容领域。
手册表明,如果订单数与where不同,则无法避免文件排序。
http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html
我也尝试过id和它的等价但是没有区别,即使我将id作为索引添加(我理解这不是必需的,因为id在MySQL中隐式索引)。
提前感谢任何想法!
标记 - 这是SHOW CREATE TABLE
CREATE TABLE `comments` (
`id` int(11) NOT NULL auto_increment,
`user_id` int(11) default NULL,
`commentable_type` varchar(255) default NULL,
`commentable_id` int(11) default NULL,
`content` text,
`created_at` datetime default NULL,
`updated_at` datetime default NULL,
`hidden` tinyint(1) default '0',
`public` tinyint(1) default '1',
`access_point` int(11) default '0',
`item_id` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `created_at` (`created_at`),
KEY `common_lookups` (`commentable_id`,`commentable_type`,`hidden`,`created_at`,`public`),
KEY `index_comments_on_item_id` (`item_id`),
KEY `index_comments_on_item_id_and_created_at` (`item_id`,`created_at`),
KEY `index_comments_on_user_id` (`user_id`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=31803 DEFAULT CHARSET=latin1
答案 0 :(得分:3)
请注意,MySQL术语 filesort 并不一定意味着它写入磁盘。它只是意味着它将在不使用索引的情况下进行排序。如果结果集足够小,MySQL将在内存中对其进行排序,这比磁盘I / O快几个数量级。
您可以使用sort_buffer_size
服务器变量增加MySQL为内存中文件排序分配的内存量。在MySQL 5.1中,默认的排序缓冲区大小为2MB,您可以分配的最大值为4GB。
更新关于Jonathan Leffler关于衡量排序时间的评论,您可以了解如何使用SHOW PROFILE FOR QUERY
,它可以让您了解每个查询执行阶段需要多长时间
答案 1 :(得分:2)
尝试在(commentable_id,created_at)上添加组合索引。