이 글은 SQL 레벨업(한빛 미디어, 미크)를 참고하여 작성하였습니다.
SQL을 잘 사용하기 위해서는 "구문"에서 "식"으로 사고를 전환해야 한다고 한다.
아래에 작성되어 있는 쿼리는 동일한 결과를 출력한다.
그러나, 두 가지의 쿼리는 성능 상 큰 차이를 보이고 있다. 어떤 쿼리가 좋은 쿼리일까?
-- 쿼리1. UNION을 이용한 조건 분기
SELECT item_name, year, price_tax_ex as price
FROM items
WHERE year <= 2001
UNION ALL
SELECT item_name, year, price_tax_in as price
FROM items
WHERE year > 2001 ;
-- 쿼리2. SELECT 구문에서 CASE 식을 사용한 조건 분기
SELECT item_name
, year
, CASE
WHEN year <= 2001 then price_tax_ex
WHEN year >= 2002 then price_tax_in
END as price
FROM items ;
2개의 쿼리는 아래의 조건을 만족하는 데이터를 출력한다.
(1) 2001년을 포함하여 그 이전은 세금을 매기기 전 가격을 출력한다.
(2) 2002년을 포함하여 그 이후는 세금을 매긴 가격을 출력한다.
이를 위해, 1번 쿼리는 UNION을 사용하여 조건 분기를 했고 2번 쿼리는 SELECT 구문에서 CASE 식을 사용하여 조건 분기를 수행했다.
결론부터 이야기하면, 2번 쿼리가 성능 상 우위에 있다. 이유는 다음과 같다.
먼저, 1번 UNION을 사용하여 조건 분기를 한 케이스를 보면 쿼리가 불필요하게 길어져있다. 쿼리가 긴 것 자체는 문제가 크지 않지만, 성능에 영향을 주는 것은 실행 계획을 보면 알 수 있다.
실행 계획을 보게되면, 1번 쿼리는 items 테이블에 Table Access Full 방식으로 2회 접근하고 있다.

반면, 2번 CASE를 이용한 쿼리는 items 테이블에 1회만 접근하며 가독성도 좋다.

SQL 격언에 이런 말이 있다고 한다.
"조건 분기를 WHERE 구로 하는 사람은 초보다.
잘 하는 사람은 SELECT 구만으로 조건 분기를 한다"
이 말을 뜯어보면, "구문"에서 "식"으로 사고를 전환해야 성능에 우위에 있는 쿼리를 작성하게 된다는 말로 풀이된다.
위 예시에서 확인한 문제를 실무에서 받게되면, 직관적으로 떠오르는 방법은 1번 쿼리에 가깝다. WHERE 절의 조건을 바꿔가며, 여러개의 SELECT 구문을 합쳐서, 복수 조건에 일치하는 하나의 결과 집합을 얻고 싶을 때 사용하게 된다.
그러나, 앞서 살펴보았듯이 UNION을 이요한 조건 분기는 외부적으로는 하나의 SQL 실행처럼 보이지만, 내부적으로는 여러개의 SELECT 구문을 실행하는 실행 계획을 가지게 되고 이에 따라 테이블 접근 횟수 증가로, I/O 비용이 크게 늘어나게 된다.
따라서, 쿼리를 작성할 때 아래와 같은 생각과 습관을 가지도록 노력하면 좋겠다.