2016-11-09 73 views
0

我有一個平臺,約10mio行,每行有15列。 索引設置爲column_1,column_2,column_3和my_time。MySQL計數(DISTINCT)非常慢 - 對子查詢更好?

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秒。

有誰知道,如何改進這個查詢,也許有子查詢? 在子查詢的情況下,你能告訴我一個示例查詢,如何提高性能?

謝謝!

+0

做一個[EXPLAIN](https://dev.mysql.com/doc/refman/5.7/en/explain.html)併發布在你的答案。 –

+3

嘗試更改爲my_time BETWEEN '2016年9月1日00:00:00' 和 '23:59:59 2016年9月30日' – Don

+0

ID:1 SELECT_TYPE:SIMPLE 表:表名 類型:ALL possible_keys: my_time,column_3 key:NULL key_len:NULL ref:NULL rows:.... Extra:Using where;使用filesort – user1891898

回答

1

你或許可以用一個適當的索引加快這:

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; 
+0

這應該會加快查詢的速度。但我認爲你還應該有一個單獨的'INDEX my_time'來加速'ORDER BY'子句 – jussius

+0

不幸的是沒有任何改進。 解釋現在顯示我: ID:1 SELECT_TYPE:SIMPLE 表:表名 類型:指數 possible_keys:my_time,column_3,speed_idx 鍵:speed_idx key_len:173 REF:NULL 行:... 額外:使用where,使用索引,使用filesort – user1891898

+0

太糟糕了,我認爲這是與給定的表一樣快。@jussius:不,這不會幫助;排序不是在'my_time'上完成的,而是在'Date(my_time)'上完成的,無論如何'my_time'已經在我的索引中。 –

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的,如果我沒有弄錯。