0

我有一个大约 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 子句。count(*)具有相同 where 条件且没有 group by的查询返回大约 150000 行。所以在实际查询中扫描的行也是可以的。但是,没有一个索引被用于对结果进行分组。我试过把索引放在cand上c,e

我的问题是,一旦应用了条件并且结果集在 tmp 表中,是否可以使用另一个索引进行排序/分组。

我已经分配了足够的内存给tmp_table_size. 因此,tmp 表肯定不会磁盘。该表正在使用MyISAM.

4

3 回答 3

0

在任何 SQL 中,无论出于何种原因,如果只对一个表执行多次扫描,我们可以为其中任何一个使用一个索引,但不能同时为两者使用。

EX:您的查询需求

  1. 一次扫描以处理 where 子句数据。(INDEX1:c 上的索引,d 很有用)
  2. 一次扫描按操作对结果集进行排序。(INDEX2:c 上的索引,e 很有用)

如果结果集中的行数更多,最好添加 INDEX2 以便排序更快。如果结果集中的行数较少,最好添加 INDEX1 以便快速处理 where 子句。

于 2014-02-04T18:35:01.577 回答
0

如果使用 (c, d , e , a , b) 创建索引,则性能会更快。这将是一个覆盖索引,不会像现在那样进行表扫描。

另外,我只是好奇,你能给我一些关于你正在使用的 Effective_month 功能的建议吗?

此外,一件重要的事情是索引大小。每个表的最大索引数和最大索引长度由每个存储引擎定义。你可以在这里阅读更多关于它的信息。在您的情况下,这不是问题,因为您正在处理我假设日期和数字。只是插入会慢一些。

于 2014-02-04T18:14:40.153 回答
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 聚合中摆脱文件排序是非常困难的。

于 2014-02-04T18:25:21.160 回答