69

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

两个表的架构(略微精简,但你明白了要点):

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

temporary那么——我的架构和/或查询 MySQL 有什么问题filesort?还是使用 ORDER BY 可以得到优化?

4

3 回答 3

118

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

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

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

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

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

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

这个 2009 年的博客说“使用文件排序”意味着无法使用索引执行排序。由于您是按计算字段排序的,所以这也是正确的。

所以,这就是“错误”。

于 2012-11-30T05:22:28.697 回答
16

针对 MySQL 5.7 ( src ) 更新:

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

  • 对 UNION 语句的评估,稍后将描述一些例外情况。

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

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

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

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

  • 结合 ORDER BY 评估 DISTINCT 可能需要一个临时表。

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

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

  • 评估多表 UPDATE 语句。

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

于 2018-03-02T08:46:47.563 回答
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

于 2014-01-14T09:41:33.697 回答