2016-09-02 19 views
0

次のSQLクエリは、Webサイトの速度を遅くします極端に! 0-1.5秒から容易に20秒以上。どのように私はそれを最適化できますか?複数のSELECTを使用してSQLクエリを最適化

SELECT DATE(a.datetime_logged) AS date, 
(SELECT COUNT(aa.data_status) FROM activity AS aa WHERE aa.id_user = '1' AND DATE(aa.datetime_logged) != CURDATE() AND DATE(a.datetime_logged) = DATE(aa.datetime_logged) AND aa.data_status = 'online') AS status_a, 
(SELECT COUNT(aa.data_status) FROM activity AS aa WHERE aa.id_user = '1' AND DATE(aa.datetime_logged) != CURDATE() AND DATE(a.datetime_logged) = DATE(aa.datetime_logged) AND aa.data_status = 'idle') AS status_i, 
(SELECT COUNT(aa.data_status) FROM activity AS aa WHERE aa.id_user = '1' AND DATE(aa.datetime_logged) != CURDATE() AND DATE(a.datetime_logged) = DATE(aa.datetime_logged) AND aa.data_status = 'streaming') AS status_s 

FROM activity AS a 
GROUP BY DATE(a.datetime_logged) 
ORDER BY DATE(a.datetime_logged) DESC 
LIMIT 40 

ここでは、テーブルの:

CREATE TABLE IF NOT EXISTS `activity` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `id_user` int(11) NOT NULL, 
    `id_channel` varchar(50) NOT NULL, 
    `id_game` int(11) NOT NULL, 
    `data_muted_server` tinyint(4) NOT NULL, 
    `data_muted_self` tinyint(4) NOT NULL, 
    `data_deafen_server` tinyint(4) NOT NULL, 
    `data_deafen_self` tinyint(4) NOT NULL, 
    `data_suppressed` tinyint(4) NOT NULL, 
    `data_status` varchar(10) NOT NULL, 
    `data_game` text, 
    `datetime_logged` datetime NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `id` (`id`), 
    KEY `index_datelog` (`datetime_logged`) 
) 
+0

あなたの質問は正しいですか?サブクエリーの部分をあなたのメイン・クエリーのwhere節に入れるべきですか?あなたは何を達成したいのですか? –

+0

私は決して複数のSELECTを使用していないので、わかりません。いくつかのグーグルリングとここからの回答の後、これが結果でした。 – Erik

+0

したがって、あなたは何らかの言葉を使って目標を記述することができます。あなたの質問を更新してみてください。 –

答えて

1

あなたはあなたがこのフォームのサブクエリを持つネストされた重いサブクエリに

+0

ああ。うわー!私はそれを知らなかった。あなたの答えに多くの感謝!私はそれを受け入れるでしょう:) – Erik

+1

短い: 'SUM(data_status = 'online')' - ブール値が0(偽)または1(真)として扱われるためです。 –

+0

非常に良い解決策は、リックジェームス:)ありがとう! – Erik

0

を置き換えるためにsum(case data_status when 'online' then 1 end) as status_aを使用することができます。

SELECT COUNT(aa.data_status) 
    FROM activity AS aa 
WHERE aa.id_user = '1' 
    AND DATE(aa.datetime_logged) != CURDATE() 
    AND DATE(a.datetime_logged) = DATE(aa.datetime_logged) 
    AND aa.data_status = 'online' 

これらは厄介です特に、あなたのカーディナリティがid_userdata_statusの場合列が少ない。 DATE(aa.datetime_logged) != CURDATE()という用語は、これらのクエリを非sargableにします。

(id_user, data_status, datetime_logged)で化合物索引を試してください。それは少し助けるかもしれない。

また、同じ化合物の指標で

SELECT COUNT(aa.data_status) 
    FROM activity AS aa 
WHERE aa.id_user = '1' 
    AND aa.datetime_logged >= DATE(aa.datetime_logged) 
    AND aa.datetime_logged < DATE(aa.datetime_logged) + INTERVAL 1 DAY 
    AND DATE(aa.datetime_logged) != CURDATE() 
    AND aa.data_status = 'online' 

を試みることができます。そうすれば、インデックススキャンが可能になります。

関連する問題