2016-11-29 8 views
0

Im以下のクエリを使用して、個々の会社ごとの上位5件の費用を計算し、それらをソートします。現在、テーブルには約300万行があり、正しく実行するには約8秒かかります。私はこれをスピードアップする方法を探しています。このSUMクエリを高速化するにはどうすればよいですか?

SELECT 
    SUM(cost) as sumw, 
    company FROM cost 
WHERE 
    datetime BETWEEN '2016-10-01' AND '2016-12-01' 
GROUP BY company 
ORDER BY sumw desc 
LIMIT 5; 

datetimeにはインデックスがあります。

はEXPLAIN:(datetime, company, cost)は、このクエリのパフォーマンスを向上させることができるかもしれ上

1 SIMPLE cost NULL ALL datetime NULL NULL NULL 3204715 50.00 Using where; Using temporary; Using filesort 

があなたのcostテーブルの上に

CREATE TABLE `cost` (
    `id` bigint(8) unsigned NOT NULL AUTO_INCREMENT, 
    `company` varchar(45) DEFAULT NULL, 
    `cost` bigint(8) unsigned DEFAULT NULL, 
    `datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `datetime` (`datetime`) 
) ENGINE=InnoDB AUTO_INCREMENT=3335830 DEFAULT CHARSET=utf8; 
+0

ハードウェアを追加します。またはクエリの前に毎日/毎時の合計を生成することができます。 SQLは可能な限り効率的に見えます。たぶん、文字列を日付にキャストして、暗黙的にそれを行う必要はありませんが、それがあなたに多くをもたらすとは想像できません。 MySQLの外では、定期的なリフレッシュを伴うマテリアライズドビューを提案するかもしれませんが、MySQLはそれらを持っていません。 – xQbert

+1

索引を含む、関連する表定義を表示するには、SQLパフォーマンスのヘルプを要求するのが慣例です。 'EXPLAIN'の出力を表示することも良い考えです。 –

+0

追加情報@ O.Jones – Ray

答えて

1

複合インデックスを作成します。とりわけ、costテーブルにこのクエリに関係しない他の多くのカラムがある場合は、試してみる価値があります。

あなたの質問には何か注意してください。

datetime BETWEEN '2016-10-01' AND '2016-12-01' 

1日 - 2016真夜中包括1-のOct-2016真夜中からの値を持つすべての行を検索します。あなたは10月と11月のデータを処理しようとしている場合あなたは

datetime >= '2016-01-01' AND datetime < '2016-12-01' 

をしたいことがあります。この第2の処方は、第1の処方よりもあなたの指標を使用する際に効率的である。

+0

クエリが正しく使用されています。電話の日付はこの質問のために追加されます。 – Ray

+0

インデックスを追加すると2秒短縮されます。 – Ray

+0

複合インデックスを追加してクエリを高速化します。** ALTER TABLE 'cost'キーを追加します。idx_date_company(' datetime'、 'company'); **そして再度テストします。新しい説明を投稿してください –

1

あなたのクエリは会社ごとの結果を計算するため、会社の列にインデックスが必要です。

ALTER TABLE cost ADD INDEX(company); 

これが役立ちます。

+0

敬意を表して、これは間違っています。 MySQLクエリは、(2016年後半)単一のインデックスを悪用することしかできません。そして、この質問者の質問の支配的な部分は、 'datetime'列の範囲検索です。 –

関連する問題