2012-02-04 4 views
2
하위 쿼리

가 부질없는 corollated 하위 쿼리최적화가 매우 빠르고

SELECT g.*, g.instaLikes + ( SELECT COUNT(*) FROM gallery_likes AS l WHERE l.gallery_id = g.id) AS likes 
FROM gallery AS g 
WHERE ( STATUS = 'approved') 
ORDER BY g.moderated_at DESC , g.id ASC 

선택으로,이 쿼리를 최적화하기 위해 노력 corollated, 나는 왼쪽을 시도 할 경우에도 느린 그 가입하세요.

SELECT g.*, (g.instaLikes + COUNT(l.id)) AS likes 
FROM gallery AS g 
LEFT JOIN gallery_likes AS l ON (g.id = l.gallery_id) 
WHERE (STATUS = 'approved) 
GROUP BY g.id 
ORDER BY g.moderated_at DESC , g.id ASC 

차라리 갤러리에서 n 배보다, 한 번 하위 쿼리를 실행할 수 있기 때문에, 개별적으로 쿼리를 수행 한 후 PHP 루프에서 함께 필드를 추가하는 가장 빠른 것 같다 옵션.

현재 갤러리에는 2,000 개의 행이 있고 gallery_likes에는 15,000 개의 행이 있습니다. 이 수치가 낮기 때문에 아직 최적화 할 필요가 없다고 생각했지만 첫 번째 쿼리는 20-30 초가 걸리고 LEFT JOIN은 100+ 초가 걸립니다!

답변

1

PHP에서 별도의 쿼리를 수행하고 데이터를 결합하는 것은 좋지 않습니다. 그러나 SQL에서 본질적으로 동일한 작업을 수행하려는 경우 할 수 있습니다. 검색어를 표 (예 : 조인)처럼 취급 할 수 있으며 파생 된 표라고합니다. 이러한 유형의 쿼리를 최적화하는 것이 더 빠르고 쉬운 방법입니다.

SELECT g.*, g.instaLikes + l.c 
FROM gallery AS g 
LEFT JOIN (
    SELECT gallery_id, COUNT(*) c FROM gallery_likes GROUP BY gallery_id 
) AS l ON g.id=l.gallery_id 
WHERE ( STATUS = 'approved') 
ORDER BY g.moderated_at DESC , g.id ASC 

이는 매우 효과적이지 않은 gallery_likes의 모든 레코드를 그룹화합니다. 그래서 일종의 필터를 추가해야합니다. 하위 선택 (파생 테이블)이 갤러리에 조인되고 외부 쿼리와 동일한 필터를 사용하는 경우의 이벤트입니다. 두 번째 쿼리와 거의 비슷하지만 가입하기 전에 데이터를 그룹화합니다. 가입하고 그룹화하는 것보다.

종종 요약 데이터 (예 : 그룹화 기준)에 가입해야하지만 때로는 비효율적 일 수있는 경우에 훌륭한 솔루션입니다. 일반적으로 EXPLAIN을 통해 알 수 있습니다.

+0

감사합니다. 메인 쿼리의 각 행에 대해 실행해야한다고 생각했기 때문에 하위 쿼리를 수행하지 않았습니다. 이것은 훌륭한 수정이었습니다 .04 초로 다시 쿼리되었습니다. – dmorrow

관련 문제