首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GROUP BY和JOIN的MySQL性能

问GROUP BY和JOIN的MySQL性能
EN

Stack Overflow用户
提问于 2011-07-01 05:11:31
回答 3查看 2.4K关注 0票数 3

在花了很多时间研究这个问题的变体之后,我想知道是否有人可以帮助我优化这个查询或索引。

我有三个临时表ref1、ref2和ref3,都定义如下,其中ref1和ref2各有6000行,而ref3只有3行:

代码语言:javascript
复制
CREATE TEMPORARY TABLE ref1 (
  id INT NOT NULL AUTO_INCREMENT,
  val INT,
  PRIMARY KEY (id)
)
ENGINE = MEMORY;

慢查询针对的是这样一个表,大约有1M行:

代码语言:javascript
复制
CREATE TABLE t1 (
  d DATETIME NOT NULL,
  id1 INT NOT NULL,
  id2 INT NOT NULL,
  id3 INT NOT NULL,
  x INT NULL,
  PRIMARY KEY (id1, d, id2, id3)
)
ENGINE = INNODB;

有问题的查询:

代码语言:javascript
复制
SELECT id1, SUM(x)
  FROM t1
  INNER JOIN ref1 ON ref1.id = t1.id1
  INNER JOIN ref2 ON ref2.id = t1.id2
  INNER JOIN ref3 ON ref3.id = t1.id3
  WHERE d BETWEEN '2011-03-01' AND '2011-04-01'
  GROUP BY id1;

临时表用于将结果集筛选为用户正在查找的项目。

解释

代码语言:javascript
复制
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref              | rows | Extra                           |
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
|  1 | SIMPLE      | ref1  | ALL    | PRIMARY       | NULL    | NULL    | NULL             | 6000 | Using temporary; Using filesort |
|  1 | SIMPLE      | t1    | ref    | PRIMARY       | PRIMARY | 4       | med31new.ref1.id |   38 | Using where                     |
|  1 | SIMPLE      | ref3  | ALL    | PRIMARY       | NULL    | NULL    | NULL             |    3 | Using where; Using join buffer  |
|  1 | SIMPLE      | ref2  | eq_ref | PRIMARY       | PRIMARY | 4       | med31new.t1.id2  |    1 |                                 |
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+

(在另一个大约有5M行的系统上,EXPLAIN show t1在列表中排在第一位,“使用where;使用索引;使用临时文件;使用文件排序”)

有没有什么明显的遗漏会阻止临时表的使用?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-07-01 05:48:45

仅在日期添加索引。由于这是第一个表的条件,而其他表只是连接,因此它将首先根据日期进行优化……连接是次要的。

票数 0
EN

Stack Overflow用户

发布于 2011-07-01 05:39:02

First filesort并不意味着要在磁盘上写入一个文件来执行排序,它是mySQL中快速排序算法的名称,请检查what-does-using-filesort-mean-in-mysql。

所以在解释中有问题的关键字是Using temporary,而不是Using filesort。为此,您可以尝试使用tmp_table_size和max_heap_table_size(在两者上设置相同的值),以允许更多的内存工作并避免临时表创建,请查看this link on the subject with remarks about documentation mistakes。

然后,您可以尝试不同的索引策略,并查看结果,但不要尝试避免文件排序。

最后一件不相关的事情,你做了一个SUM(x),但是x可以接受空值,如果你不希望组上的任何空值使你的和为空,SUM(COALESCE(x) , 0)可能更好。

票数 2
EN

Stack Overflow用户

发布于 2011-07-21 00:08:53

不是这样的吗:

代码语言:javascript
复制
SELECT id1, SUM(x)
  FROM t1
  INNER JOIN ref1 ON ref1.id = t1.id1
  INNER JOIN ref2 ON ref2.id = t1.id2
  INNER JOIN ref3 ON ref3.id = t1.id3
  WHERE d BETWEEN '2011-03-01' AND '2011-04-01'
  GROUP BY id1;

完全等同于:

代码语言:javascript
复制
select id1, SUM(x)
  FROM t1
  WHERE d BETWEEN '2011-03-01' AND '2011-04-01'
  group by id1;

额外的表是用来做什么的?我认为在另一个答案中提到的临时表是指MySQL在查询执行期间创建临时表。如果您希望创建子查询(或表)来最小化连接中所需的操作数量,那么这可能会加快查询速度,但我没有看到连接的数据被选中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6541144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档