Search
Duplicate

7장 - 서브쿼리

상태
Done
생성자
7장 - 서브쿼리

서브쿼리가 일으키는 폐해

서브쿼리의 문제점

연산비용 추가
실체적 데이터를 안가짐 → 서브쿼리에 접근 때마다 SELECT → 추가비용
복잡할수록 증가
데이터 I/O 발생
연산결과를 어딘가에 저장하다 보면 데이터량이 크면 TEMP 탈락 발생가능
최적화 불가능
서브쿼리에는 옵티마이저가 쿼리를 해석하기 위한 정보 (메타정보) 없음

서브쿼리 의존증

영수증 테이블 ⇒ 고객별 가장 오래된 구매기록을 찾기
영수증엔 고객이 여러개 들어있고, 가격도 여러개
SELECT R1.cust_id,R1.seq,R1.price FROM Receipts R1 INNER JOIN (SELECT cust_id,MIN(seq) AS min_seq FROM Receipts GROUP BY cust_id) R2 ON R1.cust_id=R2.cust_id AND R1.seq = R2.min_seq;
SQL
복사
코드 복잡
성능 문제
서브쿼리 TEMP 에 확보 → 오버헤드
제약정보(메타데이터 없음) 최적화 불능
결합을 필요→실행계획 변동 리스크
Receipts 테이블 스캔 2번
상관 서브쿼리는 답이 될 수 없다
SELECT cust_id, seq, price FROM Receptis R1 WHERE seq = (SELECT MIN(seq) FROM Receipts R2 WHERE R1.cust_id = R2.cust_id);
SQL
복사
⇒ Receipts 테이블 접근 두번 필요 ( 테이블접근1회, 기본키 인덱스접근 1회)
윈도우 함수로 결합 제거
SELECT cust_id, seq, price FROM (SELECT cust_id, seq, price, ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY seq) AS row_seq FROM Receipts) WORK WHERE WORK.row_seq=1;
SQL
복사
row_seq 로 구매 이력에 번호를 붙이고 1번만 가져옴
윈도우 함수에서 정렬이 추가되긴했으나 앞에서도 MIN() 을 썼으므로 비용차이가 별로 없음

장기적 관점에서의 리스크 관리

결합을 사용하면

알고리즘 변동의 리스크

NestedLoops, Sort Merge, Hash 중 옵티마이저가 뭘 고를지 모른다
큰 테이블 결합일때 Sort Merge 혹은 Hash 사용되기 쉽다
어느 순간 테이블이 커지면서 알고리즘 변동 가능성
⇒ 하지만 우린 주로 Mysql 이라 Nested Loops만..

환경 요인에 의한 지연 리스크(인덱스, 메모리, 매개변수 등)

TEMP 탈락 발생시 ⇒ 작업 메모리 늘려주기(트레이드오프)
장기적 관점에서 리스크를 늘리는것
실행 계획이 단순할수록 성능이 안정적
엔지니어는 기능(결과)뿐만 아니라 비기능적 부분(성능)도 보장할 책임이 있다.

서브쿼리 의존증 응용편

서브쿼리는 정말 나쁠까?

YES

22강 서브쿼리 사용이 더 나은경우

회사테이블, 사업소테이블
1 : N
결합을 먼저 수행
SELECT C.co_cd, MAX(C.district), SUM(emp_nbr) AS sum_emp FROM Companies C INNER JOIN Shops s ON C.co_cd = S.co_cd WHERE main_flg ='Y' GROUP BY C.co_cd;
SQL
복사
집약을 먼저 수행
SELECT C.co_cd, C.district, sum_emp FROM Companies C INNER JOIN (SELECT co_cd, SUM(emp_nbr) AS sum_emp FROM Shops WHERE main_flg = 'Y' GROUP BY co_cd) CSUM ON C.co_cd. = CSUM.co_cd;
SQL
복사
결과는 같지만 결합대상 레코드 수가 다르다.
첫번째는 회사테이블 4 - 사업소테이블 10
두번째는 회사 테이블 4 - 사업소테이블(CSUM) 4
⇒ 데이터양이 많다고 쳤을때 당연 작은 레코드끼리 결합하는게 좋다.