ASP,Java,SQL2008. 10. 31. 16:40
게시판의 페이징 쿼리를 연구(?)하던 중 희안한 현상을 발견했다.
다음의 두 쿼리를 보자.

1. SELECT TOP 5 * FROM
(SELECT TOP 10 * FROM tableA ORDER BY field1 ASC) AS A ORDER BY field1 DESC;

2. SELECT TOP 5 * FROM
(SELECT TOP 10 * FROM tableA) AS A ORDER BY field1 DESC;

field1은 PK로 INDEX가 ASC로 걸려있다.
어짜피 INDEX가 field1 ASC로 걸려있기 때문에 위 두개의 inner 쿼리 문은 같은 결과를 같는다.
그러나 이를 다시 DESC로 정렬하여 밑에서 5개를 가져오려고 할 때 문제가 발생한다.
2번 쿼리는 내부 쿼리 결과를 무시하고 다시 tableA 를 field1 DESC 하여 TOP 5 를 가져온다.

수행계획을 보면 차이점을 알 수 있다.


단순히 생각했을 때 inner 쿼리를 수행한 결과를 메모리에 저장하고 나서 그걸 다시 sort 하여 TOP 5를 가져오는 것이 아니네?
2번 쿼리를 보면 inner 쿼리의 내부 TOP을 수행한 뒤 바로 외부의 TOP을 수행했다. 
sort 연산은 수행하지 않았다.
둘다 select 연산은 맨 마지막에 한 번만 수행했다.

그럼 정렬 대상을 INDEX가 안걸려있는 field로 해보면 어떨까?

3. SELECT TOP 5 * FROM
(SELECT TOP 10 * FROM tableA) AS A ORDER BY field2 DESC;


하~ 이러니 sort 연산을 한다. 결과도 원하는대로 나온다.(당연하겠지만)
(※ 어? 근데 쿼리비용을 보면 3번이 더 적네?? 그래서 3번 쿼리를 실행하면서 1번쿼리도 동시에 실행시켜봤는데 비용은 같은 44.97%로 나왔다.ㅎㅎ)

암튼 이 결과 INDEX 가 걸려있는 field를 sort 할 때는 sort 연산이 이뤄지지 않는다는 걸 알았다. ASC든, DESC든.

그리고 innser 쿼리 결과를 재정렬하여 TOP 으로 가져오고자 할 경우 inner 쿼리에도 sort 를 걸어줘야 한다는 것도 알았다.
왜 그렇게 되는지는 정확히 알 수 없지만..ㅎㅎㅎ

Posted by gildong0