2014-12-28 5 views
0

테이블에서 선택하고 각각에 대해 선택하려고합니다.최소 런타임으로 SQL select 쿼리를 실행하는 방법

테이블 :

category 
+====+=======+ 
| id | title | 
+====+=======+ 
this table has list of category 

email 
+====+=======+==========+=============+ 
| id | eMail | domainId | elseColumns | 
+====+=======+==========+=============+ 
this table has list of emails but domains are in another table 

domain 
+====+========+=============+ 
| id | domain | elseColumns | 
+====+========+=============+ 
list of domains which used in email 

subscriber_category 
+========+============+ 
| userId | categoryId | 
+========+============+ 
list of emails in categories 

이제 문제는 내가 최소한의 런타임로에 이메일의 종류와 수를 나열 할 수 있습니다 어떻게? 내 시도는 200000 개의 이메일과 20 개의 카테고리에 대해 20 초를 기다리고 있습니다.

SQL :

SELECT category.*, 
(SELECT COUNT(DISTINCT subscriber_category.userId) FROM subscriber_category 
    JOIN email ON email.id=subscriber_category.userId 
    JOIN domain ON domain.id=email.domainId 
WHERE subscriber_category.categoryId=category.id 
    AND email.blackList=0 
    AND domain.blackList=0 
) AS qty 
FROM category WHERE category.userId=1 ORDER BY category.title ASC 

답변

2

이것은 당신의 쿼리입니다 :

SELECT c.*, 
     (SELECT COUNT(DISTINCT sc.userId) 
     FROM subscriber_category sc JOIN 
      email e 
      ON e.id = sc.userId JOIN 
      domain d 
      ON d.id = e.domainId 
     WHERE sc.categoryId = c.id AND e.blackList = 0 AND d.blackList = 0 
    ) AS qty 
FROM category c 
WHERE c.userId = 1 
ORDER BY c.title ASC; 

구조는 매우 합리적이고 인덱스가 성능에 도움이 될 것입니다. 첫 번째 색인은 category(userId, title, id)입니다. 이 인덱스 WHERE 절, ORDER BY 및 상관 된 하위 쿼리에 대해을 사용해야합니다.

다음은 id 열의 색인이 emaildomain 인 것으로 가정합니다. blacklist 플래그를 인덱스의 두 번째 열로 포함하면 쿼리에 약간 더 적용 할 수 있습니다. 더 중요한 것은 subscriber_category(categoryId, userId)에 대한 색인을 원합니다. 필요하지 않은 경우 count(distinct)도 제거하는 것이 좋습니다.

+0

맙소사 !!!! 귀하의 기록은'1.0499 초 '입니다. 내가 말한대로 색인을 변경했습니다. 내가 테이블들 사이에 관계를 설정하면 그건 존경인가? – Pooya

+0

@Pooya. . . 나는 당신의 코멘트에있는 질문을 이해하지 못합니다. –

+0

내가 테이블의 외래 키를 설정하면 도움이되는지 알고 싶습니까? 즉 :'email.domainId to domain.id' – Pooya