2011-01-07 3 views
1

두 가지 쿼리가 비슷하지만 성능이 매우 다르기 때문에 그 이유를 파악할 수 없습니다. 기본적으로, 나는 잠그고 처리해야하는 큰 테이블 (6M 행)의 블로그를 가지고있다. 원래 쿼리는이 모습이의MySql 쿼리 성능 퍼즐

insert into bloglock 
select b.id, [lockid], CURRENT_TIMESTAMP 
from blog b 
left join bloglock bl 
on b.id=bl.blogid 
WHERE 
State=[somestate] 
AND 
bl.BlogId IS NULL 

의미는 다음과 같습니다 블로그 ID, 잠금 ID 및 현재의 타임 스탬프로 구성된 bloglock 테이블의 항목을 만들어 블로그를 잠금 . 그러나 블로그 상태가 우리가 잠그고 자하는 것이고, 블로그가 이미 잠겨 있지 않은 경우에만 (bl.BlogId가 NULL 임)이 작업을 수행하십시오.

이 쿼리는 약 5/100 초의 속도로 매우 빠르게 실행됩니다.

하지만 다른 블로그보다 먼저 특정 블로그를 처리해야했습니다. 그래서이 분야에 인덱스를 정수 우선 순위 필드를 추가하고 쿼리를 변경 :이 우선 순위에 처음 100 백을 얻는 것을 제외하고, 이전과

insert into bloglock 
select b.id, [lockid], CURRENT_TIMESTAMP 
from blog b 
left join bloglock bl 
on b.id=bl.blogid 
WHERE 
State=[somestate] 
AND 
bl.BlogId IS NULL 
order by Priority desc 
LIMIT 100; 

동일합니다. 이 쿼리는 실행 속도가 약 30 초 정도되는 개가 느립니다. 나는 그것을 받아 들일 수있다. 그러나 퍼즐은 내가 이것을 다음과 같이 다시 썼다는 것입니다.

insert into bloglock 
select * 
from 
(select b.id, [lockid], CURRENT_TIMESTAMP 
from blog b 
left join bloglock bl 
on b.id=bl.blogid 
WHERE 
State=[somestate] 
AND 
bl.BlogId IS NULL 
order by Priority desc 
LIMIT 100) InnerQuery; 

이제는 이전과 같이 빠르게 실행됩니다. 나는 이것을 얻지 못한다. 나에게도 같은 쿼리 인 것 같아요. 물론 옵티마이 저가 동일하다고 생각 하겠지만 대신 성능에 60 배의 차이가 있습니다. 무슨 일 이니?

+0

실제 답변에 기여할만큼 잘 이해하지 못 하겠지만, 'LIMIT' 절의 위치가 작업을 수행하고 있다고 생각합니다. 첫 번째 사례의 끝에서 100까지 필터링하고 있습니다. 두 번째로는 처음에는 100으로 (할 일을 크게 줄임). – girasquid

+1

두 쿼리의 explain 계획을 살펴 보았습니까? – HLGEM

+0

@ 루케 : 두 경우 모두 괄호로 작업을 동일한 방식으로 그룹화했다면 어떻게 될지 모르겠다. –

답변

1

세 번째 쿼리가 두 번째 쿼리보다 빠를 이유가 없습니다. MySQL의 쿼리 최적화에 버그가 발생했을 가능성이 높습니다. MySQL 개발자를위한 버그 리포트를 제출하는 것을 고려해 볼 수 있습니다.

+0

이것은 분명히 나에게 맞는 것처럼 보이지만, 바보 같은 것을 놓치지 않고 버그 리포트를 제출하는 것을 꺼려합니다. –

+0

당신은 바보 같은 것을 놓치지 않았습니다. MySQL에 매우 미묘하고 특정한 것을 빠뜨릴 수있는 아주 작은 기회가 있습니다.하지만 그럴 수도 있습니다. 일반적으로 대부분의 RDBMS는 쿼리를 관계형 대수로 변환 한 다음 관계형 대수 표현을 구현하는 여러 가지 방법을 고려하여 쿼리를 최적화하여 상황에서 금식됩니다. 경우에 따라 외부 쿼리를 사용하면 일을 더 빠르게 할 수있는 다시 쓰기가 발생할 수 있습니다. 그러나이 경우 외부 쿼리는 간단하고 새로운 다시 쓰기가 발생할 수 없습니다. –

+0

현실 확인을 해주셔서 감사합니다. MySql에 대해 알리는 방법에 대해 알아 보겠습니다. –