我有一个非常简单的查询(表类型InnoDb),并EXPLAIN说MySQL必须做一个额外的传递,以找出如何按排序顺序检索行.
SELECT * FROM `comments`
WHERE (commentable_id = 1976)
ORDER BY created_at desc LIMIT 0, 5
Run Code Online (Sandbox Code Playgroud)
确切解释输出:
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
Run Code Online (Sandbox Code Playgroud)
commentable_id已编入索引.评论没有任何技巧,只是一个内容领域.
该手册表明,如果order by与where不同,则无法避免filesort.
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
Run Code Online (Sandbox Code Playgroud)
请注意,MySQL 术语文件排序并不一定意味着它写入磁盘。这只是意味着它将在不使用索引的情况下进行排序。如果结果集足够小,MySQL 会在内存中对其进行排序,这比磁盘 I/O 快几个数量级。
您可以使用服务器变量增加 MySQL 为内存中文件排序分配的内存量sort_buffer_size。在 MySQL 5.1 中,默认排序缓冲区大小为 2MB,最大可以分配为 4GB。
更新:关于 Jonathan Leffler 关于测量排序需要多长时间的评论,您可以学习如何使用SHOW PROFILE FOR QUERY它将为您提供查询执行的每个阶段需要多长时间的详细信息。