2016-11-09 5 views
0

私は約10mioの行と1つのフラットテーブルを持って、各行は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秒かかりました。

サブクエリを使用してこのクエリを改善する方法は誰にも分かりますか? サブクエリの場合は、サンプルクエリを表示して、パフォーマンスを上げる方法を教えてください。

ありがとうございました!

create index idx_speedy on table_name(column_3, my_time); 

またはそれ以上でも被覆インデックス:あなたはおそらく適切なインデックスでこれをスピードアップすることができ

+0

[EXPLAIN](https://dev.mysql.com/doc/refman/5.7/en/explain.html)を行い、あなたの答えに投稿してください。 –

+3

'2016年9月1日午前0時00分00秒' AND BETWEEN my_timeする変更してみてください '2016年9月30日午前23時59分59秒' – Don

+0

ID:1 SELECT_TYPE:SIMPLE 表:TABLE_NAME タイプ:ALL possible_keys: my_time、column_3 key:NULL key_len:NULL ref:NULL 行:.... 追加:Using where; filesortを使用する – user1891898

答えて

1

インデックスをよりよく利用するために

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

これにより、クエリの速度がかなり向上するはずです。しかし、私は 'ORDER BY'節の速度を上げるために別々の' INDEX my_time'を持たなければならないと思います。 – jussius

+0

残念ながら改善はありません。 EXPLAINは今私を示しています ID:1 SELECT_TYPE:SIMPLE 表:TABLE_NAME タイプ:インデックス possible_keys:my_time、column_3は、キー をspeed_idx:speed_idx key_lenに:173 参照:NULL 行:... 。 Extra:using where、using index、filesortの使用 – user1891898

+0

あまりにも悪いことに、私はこれが与えられたテーブルと同じくらい速いと思います。@ jussius:いいえ、それは役に立たないでしょう。ソートは 'my_time'ではなく' Date(my_time) 'に行われ、とにかく' my_time'はすでにインデックスにあります。 –

0

MySQLは我々がDate(my_time)に固執し、あなたのクエリにこのインデックスを作成することができ、関数インデックスをサポートしている場合:MySQLはこれをサポートしていないとして

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

、あなたは生成された列を作成することを決定することもできる代わりに:

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で使用可能です。

関連する問題