使用索引,使用临时,使用filesort - 如何解决这个问题?

时间:2012-11-29 19:41:34

标签: mysql optimization select temporary filesort

我正在开发一个事件跟踪系统,该系统使用少量查找表以及主要日志记录表。在我正在编写的报告中,可以选择一个对象来查看统计信息。界面按重要性降低的顺序显示所有对象(即命中)。

两个表的架构(略微修剪,但你得到了要点):

CREATE TABLE IF NOT EXISTS `event_log` (
  `event_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(5) DEFAULT NULL,
  `object_id` int(5) DEFAULT NULL,
  `event_date` datetime DEFAULT NULL,
  PRIMARY KEY (`event_id`),
  KEY `user_id` (`user_id`),
  KEY `object_id` (`object_id`)
);

CREATE TABLE IF NOT EXISTS `lookup_event_objects` (
  `object_id` int(11) NOT NULL AUTO_INCREMENT,
  `object_desc` varchar(255) NOT NULL,
  PRIMARY KEY (`object_id`)
);

我遇到问题的查询如下。它可以很好地使用我的~100个条目表,但是EXPLAIN让我有点担心。

    explain SELECT 
            el.object_id, 
            leo.object_desc, 
            COUNT(el.object_id) as count_rows
        FROM 
            event_log el 
            LEFT JOIN lookup_event_objects leo ON leo.object_id = el.object_id
        GROUP BY 
            el.object_id
        ORDER BY 
            count_rows DESC,
            leo.object_desc ASC

返回: Using index; Using temporary; Using filesort

那么 - 我的架构和/或MySQL查询在temporaryfilesort上出现了什么问题?或者它是否使用ORDER BY进行了优化?

3 个答案:

答案 0 :(得分:79)

好吧,the doc给出了“使用临时”出现的确切原因:

  

可以在以下条件下创建临时表:

     

如果存在ORDER BY子句和不同的GROUP BY子句,或者如果存在   ORDER BY或GROUP BY包含除。之外的表中的列   在连接队列中的第一个表中,创建了一个临时表。

     

DISTINCT与ORDER BY相结合可能需要一个临时表。

     

如果使用SQL_SMALL_RESULT选项,MySQL使用内存   临时表,除非查询还包含元素(描述   后来)需要磁盘存储。

快速扫描显示您患有#1。

2009年的this blog表示“使用filesort”意味着无法使用索引执行排序。由于您按计算字段进行排序,因此也是如此。

所以,这就是“错误”。

答案 1 :(得分:7)

针对MySQL 5.7(src)进行了更新:

  

服务器在以下条件下创建临时表:

     
      
  • 对UNION语句的评估,稍后将对此进行描述。

  •   
  • 评估某些视图,例如使用TEMPTABLE算法,UNION或聚合的视图。

  •   
  • 评估派生表(FROM子句中的子查询)。

  •   
  • 为子查询或半连接实现创建的表(请参见第8.2.2节“优化子查询,派生表和视图引用”)。

  •   
  • 评估包含ORDER BY子句和不同GROUP BY子句的语句,或者ORDER BY或GROUP BY包含连接队列中第一个表以外的表中的列的语句。

    < / LI>   
  • 评估DISTINCT与ORDER BY结合可能需要临时表格。

  •   
  • 对于使用SQL_SMALL_RESULT修饰符的查询,MySQL使用内存中的临时表,除非查询还包含需要磁盘存储的元素(稍后描述)。

  •   
  • 为了评估从同一个表中选择和插入的INSERT ... SELECT语句,MySQL创建了一个内部临时表来保存SELECT中的行,然后将这些行插入到目标表中。请参见第13.2.5.1节“INSERT ... SELECT语法”。

  •   
  • 评估多表UPDATE语句。

  •   
  • 评估GROUP_CONCAT()或COUNT(DISTINCT)表达式。

  •   

答案 2 :(得分:1)

以下是创建临时表的条件。 UNION查询使用临时表。

某些视图需要临时表,例如使用TEMPTABLE算法评估的表,或使用UNION或聚合的表。

如果存在ORDER BY子句和不同的GROUP BY子句,或者ORDER BY或GROUP BY包含连接队列中第一个表以外的表中的列,则会创建一个临时表。

DISTINCT与ORDER BY相结合可能需要一个临时表。

如果使用SQL_SMALL_RESULT选项,MySQL使用内存临时表,除非查询还包含需要磁盘存储的元素(稍后描述)。

通过mysql关注此链接: http://dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html