게시일: Jan 11, 2012 11:19:14 PM
- 바인드 변수를 사용한다.
오라클은 일단 SQL 문장이 실행되면 이를 메모리로 로드한 뒤 처리하는데, 가장 먼저 이전에 처리된 것 중 이와 동일한 문장이 있는지 메모리에서 찾게된다. 만약 동일한 문장이 있으면 이미 이전에 처리한 문장이므로 파싱 단계에서 하는 문법 검사, 그리고 옵티마이저가 수행하는 여러 가지 작업을 건너뛰고 이미 만들어진 실행계획대로 처리하여 결과를 반환하게 된다. 가끔씩 복잡한 쿼리를 수행하면서 맨 처음 실행할 때는 결과가 나오기까지 시간이 오래 걸리지만 두 번째부터는 결과가 빨리 나오는 경우를 볼 수 있는데, 바로 이러한 처리 방시기 때문이다.
그런데 여기서 말하는 동일한 문장은 대소문자는 물론 공백이 포함되어 있다면 이것까지 정확히 같은 문장을 의미한다. 만약 이전에 비해 공백이 하나 추가되었다면 오라클은 다른 문장으로 인식하게 된다. 따라서 WHERE 조건에 바인드 변수를 사용하면 비교 값이 달라지더라도 동일한 문장으로 인식을 하여 처리하지만, 바인드 변수를 사용하지 않는다면 모두 다른 문장으로 인식하게 되므로 처리속도가 느려지게 된다.
- 가급적 WHERE 조건에서는 인덱스 컬럼을 모두 사용한다.
- 인덱스 컬럼에 사용하는 연산자는 가급적 동등 연산자(=)를 사용한다.
- 인덱스 컬럼은 변형하여 사용하지 않는다.
- OR 보다는 AND를 사용한다.
옵티마이저의 OR-Expansion 처리는 OR 연산자로 연결된 쿼리를 UNION ALL로 변환하므로 OR보다는 AND를 사용해야 성능 좋은 쿼리를 작성할 수 있다.
- 그룹핑 쿼리를 사용할 경우 가급적 HAVING 보다는 WHERE 절에서 데이터를 필터링한다.
그룹핑 쿼리에서는 WHERE 조건뿐만 아니라 HAVING 절에 조건을 주어 반환되는 로우를 필터링 할 수 있다. 그룹핑 쿼리 순서는 WHERE 조건이 먼저 처리되므로 가급적 필터링 할 대상은 WHERE 조건에서 처리할 수 있게 쿼리를 작성하도록 한다. HAVING 절은 이미 WHERE 절에서 처리된 로우들을 대상으로 또 조건을 검사하기 때문에 좋은 성능을 발휘하기가 힘들다.
- DISTINCT는 가급적 사용하지 않는다.
- IN, NOT IN 대신 EXISTS와 NOT EXISTS를 사용한다.
☞ IN 사용
select a.*
from employees a
, departments b
where a.department_id = b.department_id
and b.department_id in (10, 20, 30);
☞ EXISTS 사용
select a.*
from employees a
where exists (select 1
from departments b
where a.department_id = b.department_id
and b.department_id in (10, 20, 30)
and rownum = 1);
- SET 연산자 사용시 UNION 대신 UNION ALL을 사용한다.
UNION 연산자는 연결된 쿼리에서 동일한 로우를 제거하고 한 로우만 반환하게 된다. 따라서 추가적으로 필터링하는 로직이 숨어 있으므로 UNION ALL 보다는 비용이 높다.