2016-09-02 2 views
0

다음 SQL 쿼리를 사용하면 웹 사이트가 느려집니다 매우! 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

아주 멋진 솔루션, Rick James :) 감사합니다! – 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()이라는 용어는 이러한 쿼리를 사용할 수 없게 만듭니다.

(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' 

을 시도 할 수 있습니다. 그러면 색인 스캔이 가능해집니다.