当order by与where子句不同时,任何避免文件排序的方法是什么?

时间:2010-05-02 17:39:03

标签: mysql

我有一个非常简单的查询(表类型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

2 个答案:

答案 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)上添加组合索引。