MySQL计数(DISTINCT)非常慢 - 使用子查询更好?

时间:2016-11-09 13:06:06

标签: mysql select count subquery distinct

我有一个平面表,大约有10十几行,每行有15列。 索引设置为column_1,column_2,column_3和my_time。

  SELECT    Date(my_time) my_time, 
            count(DISTINCT column_1) c_c1, 
            count(DISTINCT column_2) c_c2 
    FROM    `table_name` 
   WHERE    `column_3` in (10,11,100,50,213,756) 
     AND    Date(my_time) > '2016-09-01' 
     AND    Date(my_time) < '2016-09-30' 
GROUP BY    Date(my_time) 
ORDER BY    Date(my_time) ASC

结果大约需要20-30秒。

有人知道,如何改进此查询,可能是子查询? 如果是子查询,你能告诉我一个示例查询,如何提高性能?

谢谢!

2 个答案:

答案 0 :(得分:2)

您可以使用适当的索引加快速度:

create index idx_speedy on table_name(column_3, my_time);

甚至更好的覆盖指数:

create index idx_speedy on table_name(column_3, my_time, column_1, column_2);

为了更好地使用索引,请尝试避免使用where子句中的列上的函数,即避免使用Date(my_time)

  SELECT    Date(my_time) my_time, 
            COUNT(DISTINCT column_1) AS c_c1, 
            COUNT(DISTINCT column_2) AS c_c2 
    FROM    table_name
   WHERE    column_3 in (10, 11, 100, 50, 213, 756) 
     AND    my_time >= '2016-09-02' 
     AND    my_time < '2016-09-30' 
GROUP BY    Date(my_time) 
ORDER BY    Date(my_time) ASC;

答案 1 :(得分:0)

如果MySQL支持功能索引,我们可以坚持Date(my_time)并为您的查询创建此索引:

create index idx_speedy on table_name(column_3, Date(my_time), column_1, column_2);

由于MySQL不支持此功能,您可以决定创建生成的列

alter table table_name add my_date date generated always as ( Date(my_time) );

创建索引

create index idx_speedy on table_name(column_3, my_date, column_1, column_2);

并相应地重写您的查询:

  SELECT    my_date, 
            COUNT(DISTINCT column_1) AS c_c1, 
            COUNT(DISTINCT column_2) AS c_c2 
    FROM    table_name 
   WHERE    column_3 in (10, 11, 100, 50, 213, 756) 
     AND    my_date BETWEEN '2016-09-02' AND '2016-09-29' 
GROUP BY    my_date 
ORDER BY    my_date ASC;

如果我没弄错的话,从MySQL 5.7.6开始就可以使用。