18강 - 결합의 종류
Natural Join은 알아서 같은 이름의 필드를 등호로 결합하는데, 아무튼 쓰지 마라
Cross Join
•
실무에서 쓸 일 없다.
•
Cartesian 곱(데카르트 곱). ← 주로 단순 곱을 의미한다.
Inner Join
•
데카르트 곱의 내부 집합(조건이 일치하는 부분집합)
•
교집합.
Outer Join
•
데카르트 곱의 부분집합이 아니다.
→ 다만 데이터 상태에 따라 부분집합이 되기도 한다.
•
inner join과 배타적이다.
LEFT OUTER JOIN과 RIGHT OUTER JOIN은 실질적으로 같은 기능이지만, 마스터가 되는 테이블이 어느 쪽이냐에 따라 다르다.
OUTER JOIN의 경우에는 마스터 테이블에만 존재하는 키가 있을 때에는 제거하지 않고 결과에 나타낸다(위의 NULL).
19강 - 결합 알고리즘과 성능
•
NESTED_LOOPS
•
HASH
•
SORT_MERGE
위 세가지 결합 알고리즘은 주로 데이터의 크기와 결합 키의 분산에 의존한다.
NESTED_LOOPS > HASH > SORT_MERGE의 순으로 중요하다.
NESTED_LOOPS
•
이중 for문의 구조
→ 결합 조건에 맞으면 return한다.
•
한단계에서 처리하는 레코드 수가 적으므로(커서 두개) Hash나 Sort Merge에 비해 메모리 소비가 적음.
•
모든 DBMS에서 지원
•
인덱스가 있으면 B-tree를 이용한 구조로 빠르게 Scan할 수 있지만, 그렇지 않다면 사실상 무용(Full Scan)이다.
작은 구동 테이블에 결합키 인덱스는 튜닝의 기본
•
다만 결합키 자체에 대해 카디널리티가 높지 않으면(레코드 히트가 많으면) 성능이 좋지 않다.
•
예시에 나온 점포 - 점포 주문의 케이스를 생각했을 때에, 점포를 기준으로 점포 주문을 join하게 되면 hit하는 레코드들이 매우 많아서 성능이 떨어지게 된다. 이때에는 조인하는 FK의 카디널리티가 매우 높은(유일성이 보장되는) 점포 테이블을 조인하는 식으로 뒤집어서 구성하게 되면 효과적이다.
HASH
•
결합 테이블로부터 해시 테이블을 별도로 만들어서 사용하므로 메모리가 많이 소모된다.
•
메모리가 부족하면 저장소(디스크)를 사용(스왑)하므로 지연이 생긴다.
•
출력된 해시값은 입력값의 순서가 보장되지 않으므로 등치 결합(=)에만 쓸 수 있다.
용례
•
NESTED LOOPS에서 적절한 구동테이블이 존재하지 않는 경우
→ 둘 중 하나가 충분히 작지 않은 경우 == 둘의 크기가 비슷한 경우
•
둘 중 하나가 충분히 작지만, 히트되는 레코드 수가 많은 경우
•
내부 테이블의 인덱스가 존재하지 않거나 추가하기 어려운 경우.
→ NESTED LOOPS가 비효율적일 때 차선책, 동시 처리가 적은 작업(batch)의 경우에 많이 사용된다.
단점
•
OLTP(Online Transaction Processing, 우리가 아는 WAS에 대한 하나의 트랜잭션에 대한 요청)을 하는 경우에 대부분 실시간 웹 서비스일텐데, 이 때 속도가 중요하다. 한편, HASH의 경우에는 메모리를 크게 먹기 때문에 만약 여러 유저의 요청에 대해 충분히 메모리가 확보되지 않는다면 워킹 메모리를 디스크에서 스왑하게되므로 지연이 생기게 되고, 원활한 서비스를 제공하지 못할 가능성이 높아진다.
•
양쪽 테이블을 FULL SCAN하는 것이 대부분이므로, 크기가 크다면 속도에 대해 고려해야 한다.
SORT MERGE
Merge나 Merge Join이라고 부르기도 한다.
결합 대상인 테이블을 각각 결합 키로 정렬, 일치하는 결합키를 찾으면 결합한다.
•
테이블을 정렬하므로 한쪽 테이블을 모두 스캔한 시점에 결합을 완료할 수 있다.
용례
•
테이블 정렬을 생략할 수 있는 경우에는 고려해볼만한데, 그런거 아니면 NESTED LOOPS → HASH로 고려해라!
의도하지 않은 크로스 결합
삼각 결합의 경우, 연관관계가 없는 B-C에 대해서 옵티마이저가 B를 기준으로 시작하여 C, A를 join하려고 시도할 수 있다(상대적인 크기에 따라서). 하지만 이 경우 B-C의 연관관계는 없으므로 CROSS JOIN이 발생하게 되고, 의도치 않은 부하가 발생한다.
이를 위해 불필요한 JOIN 조건을 걸어서 의도한 대로 JOIN하도록 할 수 있다(어쩌면 실행계획을 지정하는 hint와 비슷한 행위를 하는 것일지도).