2012-05-14 3 views
0

아래에서 쿼리를 최적화 할 수있는 방법이 있습니까?MySQL 쿼리 최적화 합계 케이스

SELECT 
DATE_FORMAT(a.duedate,'%d-%b-%y') AS dte, 
duedate, 
SUM(CASE WHEN (typeofnotice='ddat' AND STATUS='open') THEN 1 ELSE 0 END) AS 'DDatOpen', 
SUM(CASE WHEN (typeofnotice='ddat' AND STATUS='closed') THEN 1 ELSE 0 END) AS 'DDatClosed', 
SUM(CASE WHEN (b.action='tagunchanged' AND STATUS='closed') THEN 1 ELSE 0 END) AS 'DDatUnchanged', 
SUM(CASE WHEN (typeofnotice='rss' AND validindicator IS NULL AND STATUS='open') THEN 1 ELSE 0 END) AS 'RSSValidation', 
SUM(CASE WHEN (typeofnotice='rss' AND validindicator=1 AND STATUS='open') THEN 1 ELSE 0 END) AS 'RSSValidOpen', 
SUM(CASE WHEN (typeofnotice='rss' AND validindicator=1 AND STATUS='closed') THEN 1 ELSE 0 END) AS 'RSSValidClosed', 
SUM(CASE WHEN (typeofnotice='rss' AND validindicator=0) THEN 1 ELSE 0 END) AS 'RSSInvalid', 
SUM(CASE WHEN (typeofnotice='copernic' AND validindicator IS NULL AND STATUS='open') THEN 1 ELSE 0 END) AS 'CopernicValidation', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=1 AND validindicator=1 AND STATUS='open') THEN 1 ELSE 0 END) AS 'CopernicValidAwardOpen', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=1 AND validindicator=1 AND STATUS='closed') THEN 1 ELSE 0 END) AS 'CopernicValidAwardClosed', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=1 AND validindicator=0) THEN 1 ELSE 0 END) AS 'CopernicInvalidAward', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=0 AND validindicator=1 AND STATUS='open') THEN 1 ELSE 0 END) AS 'CopernicOpportunityValidOpen', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=0 AND validindicator=1 AND STATUS='closed') THEN 1 ELSE 0 END) AS 'CopernicOpportunityValidClosed', 
SUM(CASE WHEN (typeofnotice='copernic' AND isaward=0 AND validindicator=0) THEN 1 ELSE 0 END) AS 'CopernicOpportunityInvalid', 
SUM(CASE WHEN (typeofnotice='copernic' AND STATUS='limited') THEN 1 ELSE 0 END) AS 'CopernicLimitation', 
SUM(CASE WHEN ((validindicator IS NULL OR validindicator = 1) AND STATUS='open') THEN 1 ELSE 0 END) AS 'TotalNotices', 
SUM(CASE WHEN (validindicator=1 AND STATUS='closed') THEN 1 ELSE 0 END) AS 'TotalCompleted', 
SUM(CASE WHEN (validindicator=0 AND (typeofnotice='wget' OR typeofnotice='copernic' OR typeofnotice='rss')) THEN 1 ELSE 0 END) AS 'TotalInvalid' 
FROM tblNotices AS a LEFT JOIN tblTransactions AS b 
ON a.id = b.noticeid WHERE b.noticeid IS NOT NULL 
WHERE duedate >= '2011-04-04 00:00:00' AND a.duedate <= '2012-05-08 24:00:00' 
GROUP BY dte 
ORDER BY dueDate ASC; 

tblTransactions은 150 만 행 tblNotices을 가지고 900K 행이 있습니다.

쿼리가 약 1 분 동안 실행됩니다. 정상입니까? 이 쿼리를 최적화 할 수있는 방법이 있습니까?

Describe 'table' and Explain Select

는 여기가 어떤 조언되어 있습니다 .. DATE_FORMAT 기능은 여기에 정말 성능을 죽이고 생각? 그것은 약 58 초 동안 실행됩니다.

+1

검색어 및 두 테이블의 스키마에 대해 'EXPLAIN' 출력을 게시하십시오. – eggyal

답변

1

쿼리는 SUM (IF()) 인스턴스 제외하고 ... 간단 보인다.

귀하의 질의는 거래 좌 - 가입,하지만 b.noticeID가 null가 아닌 경우가 있습니다. 이 두 가지 조합은 정상적인 "JOIN"또는 "INNER JOIN"의미를 의미합니다. 당신의 Where 절에 대한

같이, 나는 당신이 때문에 날짜에 간단한 인덱스가 있는지 확인합니다. 테이블에 "MUL"(다중 키) 색인이 표시되며 기한이 해당 키의 첫 번째 부분인지 확인하거나 적어도 하나의 색인이 첫 번째 필드로 양분되어 있습니다.

다음으로 그룹이 작성됩니다. 만기 날짜의 날짜 형식으로 그룹을 만들고 있기 때문에 테이블 인덱스와 일치하는 duedate만을 기준으로 그룹을 나갈 수 있습니다. 시각적으로 형식화 된 문자열은 어차피 타고 올라갈 것입니다. 그리고 Order By는 또한 duedate (꽤 형식화 된 문자열 버전이 아닙니다)를 기반으로하므로 좋을 것입니다. 쿼리 자체 ... 제공하는 범위 내에서 얼마나 많은 레코드의 날짜 범위에 관해서는

.

개정

쿼리가 실제로 보는 페이지 데이터에 갈 필요가 없습니다, 그래서 당신은 당신의 쿼리에 사용되는 요소의 다중 인덱스를 가진 활용할 수있을 것 전체 기록에서 개별 요소. 데이터가 인덱스 키의 일부가 될 수 있으므로 쿼리는이를 직접 사용할 수 있으며 페이지를 이동하지 않아도됩니다.

에 대한 설명을 표시

색인에(DueDate, status, IsAward, TypeOfNotice, ValidIndicator)

또한 쿼리의 alias.fields에 대한 설명이 필요합니다. 때로 명시 적으로 "a." 별칭 및 다른 시간에는 별칭이 없습니다. 당신이나 다른 도움을 제공하려고 노력하는 다른 사람들에게 질문을하기 위해 일하는 사람들에게. 적절한 별명을 가진 모든 필드를 명시 적으로 쉽게 참조하여 어떤 테이블에서 어떤 컬럼의 모호성을 방지합니다. 예, 여기에 테이블 구조를 제공했지만 미래는 구조를 계속 돌아 보는 것보다 쉽게 ​​만들 수 있습니다.

+0

날짜 범위 내에 428173 개의 레코드가 있습니다. 그룹 단락을 생략했지만 여전히 기쁨은 없습니다. 나는 한 줄의 결과를 주었다. 또한 'duedate by group'을 사용했지만 예기치 않은 결과를 얻었습니다. 각 행의 날짜는 같지만 시간이 다릅니다. –

+0

@ user877880, ok, 날짜/시간 스탬프인데 의미가 있습니다. 분명히 원합니다. "하루 당"기준으로합니다. 개정 된 대답도. – DRapp

+0

그러나 INNER JOIN에 대한 귀하의 제안은 6 초의 질의에 고통을 겪었습니다. 방금 DATE_FORMAT 대신 Date() 함수를 사용하여 이전 쿼리보다 성능이 좋습니다. –

0

음, 즉

FROM tblNotices AS a LEFT JOIN tblTransactions AS b 
ON a.id = b.noticeid WHERE b.noticeid IS NOT NULL 

FROM tblNotices AS a INNER JOIN tblTransactions AS b 
ON a.id = b.noticeid 

두번째 빠를 수와 동일하다.

왜 두려움에 의해 그룹화하지 않습니까? 그렇다면 DATE_FORMAT()을 생략 할 수 있습니다.하지만 이것은 땅콩 일뿐입니다. 이를 생략하면 ORDER BY도 필요하지 않습니다. GROUP BY에 관련되어 있기 때문입니다.

그 외에도 할 수있는 일이 많지 않습니다. 그것을 얻을 수로