Ch.3 SQL 조건 분기 - 구문에서 식으로

텐저린티·2023년 8월 7일
0

SQL레벨업

목록 보기
3/10

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

  • UNION을 이용해 조건분기하는 방식은 성능적 측면에서 굉장히 큰 단점
  • 내부적으로 여러 SELECT 구문을 실행하는 실행계획
  • 테이블 접근 횟수 증가 → I/O 비용 증가
  • CASE를 이용한 조건분기 권장

UNION을 사용한 조건 분기와 관련된 간단한 예제

핵심

  • CASE 식 사용한 조건 분기
    • 을 바탕으로 하는 사고
    • SQL 마스터키 = 구문에서 으로 사고를 변경
    • 절차지향의 IF가 생각날 때마다 ‘CASE로는 어떻게 할까’를 고민

문제

  • 2001년까지는 세금 미포함, 2002년부터는 세금 포함
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 >= 2002;
  • 문제점
    • 가독성 측면
    • 성능 측면
      • TABLE ACCESS FULL 2회 발생
      • 테이블 크기에 따라 읽기 비용 선형 증가
      • 물리자원(저장소 I/O 비용) 소비

WHERE 구에서 조건 분기 하는 사람 = 초보자

  • 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;
  • 좋은 점
    • 가독성 측면
    • 성능 측면
      • TABLE ACCESS FULL 1회

9장. 집계와 조건 분기

집계 대상으로 조건 분기

  • 지역별, 성별 별 인구수

UNION 방법

select prefecture, 
			 sum(pop_men) as pop_men,
			 sum(pop_wom) as pop_wom
	from ( select prefecture, pop as pop_men, null as pop_wom
						from population
				 where gender = '1'
				 union
				 select prefecture, null as pop_men, pop as pop_wom
						from population
				 where gender = '2') temp
group by prefecture;
  • 이러한 방법 자체가 절차지향적 사고
  • 테이블을 각자 select로 구하고, merge
  • 테이블 풀 스캔 2 회

CASE 방법

select prefecture,
			 sum(case when gender = '1' then pop else 0 else) as pop_men,
			 sum(case when gender = '2' then pop else 0 else) as pop_wom
	from population
group by prefecture;
  • 간단한 쿼리
  • 테이블 풀 스캔 1회
  • 대부분의 경우 UNION으로 할 수 있는 쿼리는 CASE로도 가능 (아닌 경우도 있음)

집약 결과로 조건 분기

핵심

  • where, having 에서 조건 분기하는 사람 = 뉴비

문제

  • 조건
    • 소속팀이 1개면 팀 이름 그대로 출력
    • 소속팀 2개면 ‘2개를 겸무’ 출력
    • 소속팀 3개 이상이면 ‘3개 이상을 겸무’ 출력

UNION 방법

  • union으로 merge한 이상, 구문 레벨 분기일 뿐
  • where과 큰 차이 없음
  • case를 이용해서 식 레벨 분기로 바꿔야 함
  • 테이블 풀 스캔 3회
select emp_name, max(team) as team
	from employees
group by emp_name
having count(*) = 1
union
select emp_name, '2개를 겸무' as team
	from employees
group by emp_name
having count(*) = 2
union
select emp_name, '3개 이상을 겸무' as team
	from employees
group by emp_name
having count(*) >= 3;

CASE 방법

  • 테이블 풀 스캔 1회
  • 집약 함수 결과가 스칼라(분할 불가값)
select emp_name,
			 case when count(*) = 1 then max(team)
					  when count(*) = 2 then '2개 겸무'
						when count(*) >= 3 then '3개 이상 겸무'
			 end as team
	from employees
group by emp_name;

10장. 그래도 UNION 필요한 경우

UNION 사용할 수밖에 없는 경우

  • SELECT 구문에서 사용하는 테이블이 다른 경우
  • FROM 구에서 테이블 결합해 CASE 식으로 결과 얻을 수 있지만, 필요없는 결합임.

UNION을 쓰는게 성능적으로 더 좋은 경우

  • 인덱스를 적절하게 쓴 경우
  • 테이블 풀 스캔보다 성능 우세일 가능성

union 방법

  • (dx, fx) 쌍으로 3개의 인덱스가 있는 상태
select key, name, d1, f1, d2, f2, d3, f3
	from three
where d1 = '2013-11-01' and f1 = 't'
union
select key, name, d1, f1, d2, f2, d3, f3
	from three
where d2 = '2013-11-01' and f2 = 't'
union
select key, name, d1, f1, d2, f2, d3, f3
	from three
where d3 = '2013-11-01' and f3 = 't'
SELECT STATEMENT
	SORT UNIQUE
		UNION-ALL
			TABLE ACCESS BY INDEX ROWID
				INDEX RANGE SCAN
			TABLE ACCESS BY INDEX ROWID
				INDEX RANGE SCAN
			TABLE ACCESS BY INDEX ROWID
				INDEX RANGE SCAN

OR 방법

  • 3회 인덱스 스캔 vs 1회 테이블 풀 스캔
  • 테이블 크고, 조건 분기로 선택되는 레코드 수가 적으면 union 이 더 성능 우세
select key, name, d1, f1, d2, f2, d3, f3
	from three
where (d1 = '날짜' and f1 = 't')
	or  (d2 = '날짜' and f2 = 't')
  or  (d3 = '날짜' and f3 = 't');
SELECT STATEMENT
	TABLE ACCESS FULL 

IN 방법

  • OR 과 동일한 실행계획
select key, name, d1, f1, d2, f2, d3, f3
	from three
where ('날짜', 't') in ((d1, f1), (d2, f2), (d3, f3));

CASE 방법

select key, name, ...
	from three
where case when d1 = '날짜' then f1
					 when d2 = '날짜' then f2
					 when d3 = '날짜' then f3
					 else null
			end = 't';

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

구문 기반 vs 식 기반

  • SQL 뉴비 = 절차 지향적 세계
  • SQL 석유 = 선언적 세계
  • 차이는 기본단위의 차이 = 구문 vs
  • SQL은 CASE 식으로 조건 분기
  • SQL 구문 내부에도
  • 암튼 SQL 조건분기는 으로 이뤄져 있다.

정리

  • SQL 성능 = 저장소 I/O 감소 정도
  • UNION 조건 분기 < CASE 조건 분기
  • 테이블 스캔 감소시킬 수 있는 효자 CASE
  • 구문에서 식으로 패러다임 전환
profile
개발하고 말테야

0개의 댓글

관련 채용 정보