mysql - 当 order by 与 where 子句不同时,有什么方法可以避免文件排序?

标签 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 已编入索引。评论没有什么技巧,只是一个内容字段。

手册建议,如果 order by 与 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

最佳答案

请注意,MySQL 术语文件排序 并不一定意味着它写入磁盘。这只是意味着它将在不使用索引的情况下进行排序。如果结果集足够小,MySQL 会在内存中对其进行排序,这比磁盘 I/O 快几个数量级。

您可以使用 sort_buffer_size 增加 MySQL 分配给内存中文件排序的内存量。服务器变量。在 MySQL 5.1 中,默认排序缓冲区大小为 2MB,您可以分配的最大值为 4GB。


更新:关于Jonathan Leffler关于measuring how long the sorting takes的评论,你可以学习如何使用SHOW PROFILE FOR QUERY这将为您详细说明查询执行的每个阶段需要多长时间。

关于mysql - 当 order by 与 where 子句不同时,有什么方法可以避免文件排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2754319/

相关文章:

python - 在Python中从mysql查询中删除引号

mysql - MySQL Workbench 6.3 (Win x64) 中的 useLegacyAuth=1 因传递错误类型而失败,预期为 sql::SQLString

php - 带子查询的慢 MySQL 查询

javascript - 尝试将 contenteditable div 的内容保存到 MySQL 数据库

mysql - mysql如何获取一条记录的大小

MySQL 删除或选择并删除

java - JPA 整数转换为字符串以进行 MySQL 查询

Mysql 通配符用于显示 where 子句中的所有值

mysql - 在实体管理器上查询时需要避免使用 “in PersistenceUnit”

MySQL NOW() 在 Doctrine DBAL 插入中?