我有一个大约有8M行和35列(整体大小为1G)的表。这用于涉及多级group by
条件的报告。这是一个这样的查询。
explain select min(a), max(a), avg(a), sum(b) from test where (c=2 or c=20 or c=18 or c=21 or c=12) and d>='2013-01-01' and d <= '2013-12-01' group by c,e;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 7
ref: NULL
rows: 154911
Extra: Using where; Using temporary; Using filesort
1 row in set (0.00 sec)
这需要大约1.8秒才能执行。主键位于c,d
上,用于评估where子句。具有相同where条件且没有group by的count(*)
查询返回大约150000行。因此,在实际查询中扫描的行也可以。但是,没有一个索引被用于分组结果。我已尝试在c
和c,e
上添加索引。
我的问题是,在应用条件并且结果集在tmp表中时,可以使用另一个索引进行排序/分组。
我为tmp_table_size
分配了足够的内存。所以,tmp表肯定不会进入磁盘。该表格正在使用MyISAM
。
答案 0 :(得分:0)
如果使用(c,d,e,a,b)制作索引,则性能会更快。这将是一个覆盖索引,并且表扫描将不会像现在那样完成。
另外,我只是好奇,你能给我一些关于你正在使用的effective_month功能的指示吗?
另外,一个重要的是索引大小。每个存储引擎定义每个表的最大索引数和最大索引长度。您可以阅读更多相关信息here。在你的情况下,这不会是一个问题因为你正在处理我假设日期和数字。只是插入的速度会慢一些。
答案 1 :(得分:0)
覆盖索引可能有所帮助。假设这是您的查询:
select min(a), max(a), avg(a), sum(b)
from test
where (c=2 or c=20 or c=18 or c=21 or c=12) and
d >= '2013-01-01' and d <= '2013-12-01'
group by c, e;
覆盖指数为test(c, d, e, a, b)
。
然而,很难摆脱MySQL聚合中的文件排序。
答案 2 :(得分:0)
在任何SQL中,出于任何原因,如果只在一个表上执行多次扫描,我们可以为其中任何一个使用一个索引,但不能同时使用两个。
EX:您的查询需要
如果结果集中的行数更多,则最好添加INDEX2,以便快速排序。 如果结果集中的行数较少,则最好添加INDEX1,以便快速处理where子句。