Search
Duplicate

3장 - SQL의 조건 분기

상태
Done
생성자
3장 - SQL의 조건 분기

8강. UNION을 사용한 쓸데없이 긴 표현

UNION을 사용한 조건 분기는 일반적으로 조건이 다른 WHERE 구문을 합쳐서, 복수의 조건에 일치하는 결과 집합을 얻고자 사용한다.
하지만, UNION을 사용한 조건 분기는 외부적으로는 하나의 SQL 구문을 실행하는 것처럼 보이지만, 내부적으로는 여러 개의 SELECT 구문을 실행함으로, I/O 비용이 크게 증가한다.
일부 예외적인 경우를 제외하면, 조건 분기를 할 때 UNION을 사용해서는 안된다.
UNION으로 조건 분기를 하는 경우의 문제
1.
SQL 구문이 길어진다.
2.
테이블에 자주 접근하게 되므로 I/O 비용이 크다. → 테이블의 크기가 커질수록 비용이 선형적으로 커진다.
CASE식을 사용한 조건 분기로 성능과 가독성이 좋아졌다.
SQL 구문의 성능을 실행 계획 레벨에서 판단해야 한다.
→ SQL 구문에는 어떻게 데이터를 검색할지를 나타내는 “접근 경로”가 드러나있지 않기 때문
UNION과 CASE의 차이
UNION을 사용한 조건 분기는 SELECT ‘구문’을 기본 단위로 분기 → 절차 지향형의 방식
CASE 식을 사용한 조건 분기는 ‘식’을 바탕으로 하는 분기

9강. 집계와 조건 분기

1.
집계 대상으로 조건 분기
UNION을 사용한 절차 지향적인 방식의 집계
→ SQL 구문이 복잡하고 길다.
→ 테이블에 2번 접근한다.
CASE 식을 사용한 방식
→ SQL 구문이 간단하다.
→ UNION 방식에 비해 I/O 비용이 감소한다.
표측/표두 레이아웃 이동 문제
2.
집약 결과로 조건 분기
UNION을 사용한 방식
WHERE구가 아니라, HAVING 구에 조건 지정 → 조건 분기가 레코드값이 아닌, 집합의 레코드 수에 적용된다.
하지만, 여전히 구문 레벨의 분기이다. → WHERE 구를 사용할 때와 비용이 크게 다르지 않다.
CASE 식을 사용한 방식
UNION 방식에 비해 테이블 접근 비용과 GROUP BY를 하기 위한 HASH 연산이 모두 1/3로 줄었다.

10강. 그래도 UNION이 필요한 경우

1.
UNION을 사용할 수밖에 없는 경우
여러개의 테이블에 대한 SQL 구문의 결과를 합치는 경우
2.
UNION을 사용하는 것이 성능적으로 더 좋은 경우
UNION을 사용했을 때 성능 좋은 (압축을 잘하는) 인덱스를 사용하는 경우, table full scan이 발생하는 경우보다 성능적으로 좋을 수 있다.
원본 테이블
만들고자 하는 테이블
UNION을 사용한 방법
→ 위의 쿼리를 최적의 성능으로 수행하려면 다음과 같은 필드 조합에 대한 인덱스가 필요하다.
→ 위의 실행 계획에서는 모든 SELECT 구문이 각각의 인덱스를 사용하고 있다.
→ 인덱스 스캔의 경우, 테이블의 레코드 수가 많고 WHERE 구에서 레코드 수를 많이 압축할수록(조건에서 많이 걸러질수록) 성능이 좋아진다.
→ 주. 위의 예시처럼 레코드 수가 적은 경우는 table full scan과 index scan의 성능 차이가 크지 않아서 옵티마이저가 table full scan을 선택할 수도 있다.
OR를 사용한 방법
→ 위 쿼리의 결과는 UNION을 사용한 경우와 같다.
→ 하지만 실행 계획을 보면, 테이블에 대한 접근이 1번으로 줄어든 반면 인덱스 스캔 대신 table full scan이 사용되었다.
→ 3번의 인덱스 스캔과 1번의 테이블 풀 스캔 중에서 어떤 것이 더 성능이 좋은지는 테이블의 크기와 검색 조건에 따른 레코드 히트율에 따라 다르다.
IN을 사용한 방법
→ 다중 필드 혹은 행식(row expression)이라는 기능을 사용한 방법
→ IN의 매개변수로는 스칼라뿐만 아니라 값의 리스트(배열)를 입력할 수도 있다.
→ OR을 사용한 방법과 실행 계획이 같다.
다중 필드
CASE 식을 사용한 방법
→ OR와 IN을 사용한 경우와 실행 계획이 같다.

11강. 절차 지향형과 선언형

결론 : 일반적으로 조건 분기는 UNION이 아닌 CASE 식을 사용하는 것이 가독성과 성능적으로 좋다.
1.
구문 기반과 식 기반
SQL의 기본적인 체계는 선언형으로, 구문이 아니라 이 중심이다.
SELECT, FROM, WHERE와 같은 SQL 구문의 각 부분에 작성하는 것은 모두 이다.
필드 명, 상수만 기술하는 경우에도 마찬가지
→ 필드 명만 있다면 ‘연산자가 없는 식’ , 상수만 있다면 ‘변수와 연산자가 없는 식’이다.

정리

SQL의 성능은 저장소의 I/O 비용을 얼마나 감소시킬수 있는지가 관건
UNION으로 조건 분기를 표현할 때는 가독성에 대해 생각해볼것.
IN 또는 CASE 식으로 조건 분기를 표현할 수 있다면, 테이블에 대한 접근 비용을 감소시킬 수 있다.
구문보다는

연습문제

UNION과 IN, OR의 결과가 같고, CASE 식을 사용한 경우 결과가 다르다.
→ CASE 식의 WHEN 구문은 단락 평가를 수행하기 때문에, 특정 조건이 TRUE라면 거기서 평가가 중단되며, 나머지 조건 분기에 대한 평가는 생략한다.
→ 반면, UNION과 IN, OR는 모든 조건 분기를 평가하므로 결과가 같다.
→ UNION과 결과적으로 동치인 방식은 IN 구문

Reference