728x90
조인에 대해서 2개의 테이블이 있을 때 어떤 테이블이 left에 있는게 맞을까?
흔하게 그리고 항상 사용하게 되는 join에 있어서 left에 위치하게 되는 혹은 먼저 나오게 되는 테이블에 대해서 정리해보겠습니다.
즉, 마스터-디테일 구조에서의 driving table을 정하는 기준을 확인해보겠습니다.
1. 마스터 테이블, 디테일 테이블이란?
1) 원장성 테이블(master table)
- 업무의 핵심 개체(entity)들로서 주로 업무성격의 주체(Subject, Source)에 대한 정보를 담고 있으며, 부속된 많은 자식 테이블(child table)들을 거느리고 있음
- 주요 엔터티(Entity)를 관리하는 테이블로, 주로 고유 ID(primary key)와 메타데이터를 포함, 다른 테이블의 참조 대상
- Customer, Product, Employee 등
- 이력 테이블(History Table)도 부속되어 있음
- dw시스템을 구축할 때도 이와 같은 원장성 테이블은 아주 중요한 핵심 테이블(Key Table) 역할을 함
- 현재(가장 최신)의 상태와 속성정보를 유지, 관리
- 속성들도 시간이 흘러도 변하지 않는 불변 속성과 시간의 경과에 따라 상태가 변하는 가변 속성이 존재
- 불변 속성: "생년월일", "주민번호", "성별"
- 가변 속성: "건강상태", "주소", "전화번호"
2) 거래성 테이블(transactional table, detail table)
- 행위(behavior) 테이블을 말하는 것으로, "카드거래내역 테이블, 입출금내역 테이블" 등이 해당
- Master 테이블과 1:N 관계를 가지며, Master 엔터티와 관련된 세부 데이터를 저장하는 테이블
- ex) Order, OrderDetails, TransactionHistory 등
- 주로 Master 테이블의 각 엔터티와 관련된 개별 트랜잭션(이벤트)을 기록
- 원칙적으로 거래성 테이블은 등록만 되는 개념이지, 변경되는 개념이 아님
- ex) "카드거래내역 테이블"을 본다면, 카드 승인시에 승인기록이 저장되고, 이를 정정하기 위해서는 변경이 발생하는 것이 아니라, 취소기록을 등록하게 됨
- 어떠한 경우도 한번 등록된 내용을 변경하는 경우는 없음 → 따라서 이력 테이블이 없음
- detail table 주요 특징:
- 외래 키: Detail 테이블은 항상 Master 테이블의 Primary Key를 참조
- 1:N 관계: Master 테이블의 한 행이 Detail 테이블의 여러 행과 연결
- 종속적 데이터: Detail 테이블은 Master 테이블의 데이터 없이는 의미가 없으며, 주로 Master 데이터를 보완
Customer (Master Table)
-------------------------
customer_id | name
-------------------------
1 | Alice
2 | Bob
Order (Detail Table - Transactional)
-------------------------------------
order_id | customer_id | amount
-------------------------------------
101 | 1 | 100
102 | 1 | 200
103 | 2 | 150
- Master: Customer
- Detail: Order
3) 이력성 테이블(history table, detail table)
- 이력성 테이블은 Master 테이블의 각 엔터티와 관련된 변경 이력이나 상태를 저장
- 원장성 테이블의 외부에 동일한 구조를 가지고 있는 외부 이력 테이블(Outer History Table) 형태가 있을 수 있고 원장성 테이블의 내부에 상위키(upper key) 속성 컬럼을 포함시켜 내부순환(recursive) 구조를 가진 내부 이력 테이블(Inner History Table) 형태가 있을 수 있으며, 원장성 테이블이 중요. 상태 정보만을 이력 관리하는 중요 항목 이력 테이블(Hot-Item History Table) 구조로 구성될 수 있음
- 변경된 상태정보를 시작시점~종료시점의 구간으로 하는 선분이력(Line History) 형태로 관리될 수도 있고 변경시점을 기준으로 하는 점 이력(Point History) 형태로 이력은 관리될 수 있습니다. 선분 이력 테이블(Line History Table)은 주로 원장성 테이블에 구축되며 점이력 테이블(Point History Table)은 주로 양면성 테이블에 일반적으로 구축
Employee (Master Table)
-------------------------
employee_id | name
-------------------------
1 | Alice
2 | Bob
EmployeeHistory (Detail Table - History)
-----------------------------------------
history_id | employee_id | role | effective_date
-----------------------------------------------------
201 | 1 | Manager | 2024-01-01
202 | 1 | Director | 2025-01-01
203 | 2 | Engineer | 2024-05-01
- Master: Employee
- Detail: EmployeeHistory
4) 거래성 vs 이력성 테이블
- Transactional Table: 실시간 이벤트 데이터를 저장하며, Master 테이블의 특정 엔터티에 종속
- Historical Table: 시간에 따른 Master 테이블 엔터티의 상태 변경 이력을 저장하며, Detail 테이블의 역할 수행
2. 조인 시 driving table
1) Driving table과 Driven table
- 선행 테이블(Driving Table) : 조인 시 먼저 액세스 되는 테이블로, WHERE 절로 최대한 데이터를 거를 수 있는 테이블 / 데이터 양이 적은 테이블로 선정
- 후행 테이블(Driven Table): 조인 시 나중에 액세스 되는 테이블 (Driving이 아닌 나머지 테이블)조인을 위한 인덱스가 생성되어 있는 것이 좋음(없다면 Driving Table에서 도출된 결과와 맞는지 매번 FULL TABLE SCAN으로 일일이 비교해야 하기 때문)
2) RBO
- 규칙에 의한 순서: RBO는 특정 규칙을 따르며, 종종 테이블의 크기나 인덱스 유무에 관계없이, 조인 순서가 하드코딩된 규칙에 의해 결정
- 인덱스를 이용한 액세스 방식이 전체 테이블 액세스 방식보다 우선순위가 높음
- 조인 칼럼에 대한 인덱스가 양쪽 테이블에 모두 존재할 때, 우선순위가 높은 테이블을 선택
- 조인 칼럼에만 인덱스가 존재하는 경우에는 인덱스가 없는 테이블을 먼저 선택하여 조인 수행
- 만약 조인 테이블의 우선순위가 동일하지 않다면, FROM 절에 나열된 테이블의 역순으로 수
- 성능 저하: RBO는 테이블 크기나 데이터 분포를 고려하지 않기 때문에, 큰 테이블을 먼저 읽고 작은 테이블을 뒤에 조인할 경우 성능이 저하될 수 있음
3) CBO
- 규칙의 우선순위가 아닌 쿼리를 수행하는데 소요되는 예상 비용을 바탕으로 실행계획을 생성
- 통계정보, DBMS 설정정보, DBMS 버전 등의 차이로 인해 똑같은 SQL문이라도 서로 다른 실행계획이 생성될 수 있음
- Driving Table: CBO에서는 보통 작은 테이블을 먼저 읽도록 최적화, 작은 테이블을 Driving Table로 선택하여, 그 결과를 기반으로 다른 테이블을 필터링하거나 결합(master table)
- Driven Table: Driving Table의 결과와 결합되는 테이블로, 대체로 후속 테이블이며, Driving Table에 의해 필터링(detail table)
- 두 칼럼 모두 각각 인덱스가 있는 경우
- 옵티마이저의 판단으로 각 테이블의 통계 정보에 있는 레코드 건수에 따라 driving, driven 결정
- right 테이블의 칼럼에만 인덱스가 있는 경우
- left 테이블의 반복된 풀 스캔을 막기 위해 left 테이블을 driving
- left 테이블의 칼럼에만 인덱스가 있는 경우
- left 테이블이 driving, right이 drivien
- 두 테이블 모두 칼럼에 인덱스가 없는 경우
- 어느 테이블을 driving으로 선택하더라도 driven 테이블의 풀스캔은 발생하기 때문에 스캔되는 레코드 수에 따라 옵티마이저가 적절히 driving 테이블을 선택
- 두 칼럼 모두 각각 인덱스가 있는 경우
- 주체가 되는 테이블을 왼쪽에 배치.
- 상대적으로 더 작은 테이블을 왼쪽에 두어 성능 최적화.
- 외부 키가 있는 테이블을 오른쪽에 두고, 참조하는 테이블을 왼쪽에 배치.
- 필터 조건이 적용된 테이블을 왼쪽에 배치하여 데이터 양 축소.
성능을 좋게 만드려면,
"구동테이블(Driving Table)이 작을수록"
&
"내부 테이블(Inner Table)의 결합키 필드에 인덱스가 존재"
3) 결론
- inner join의 경우, 옵티마이저가 최적의 실행계획에 따라 결정
- 최적의 실행계획은 위의 "구동테이블이 작고 내부테이블 결합키에 인덱스가 존재하는 경우" 라는 조건에 따라 실행 비용을 최소화하는 방향으로 결정
- 만약 두 테이블 모두 인덱스가 있거나 없다면 레코드 수에 따라 옵티마이저가 알아서 구동테이블을 선택
- Outer Join 은 반드시 Outer 가 되는 테이블을 먼저 읽어야하기 때문에 옵티마이저가 조인의 순서를 선택할 수 없음
- Left Outer Join 일 땐 왼쪽 테이블이, Right Outer Join 일 땐 오른쪽 테이블이 드라이빙 테이블이 됨
- left에 모든 정보가 나와야 하는 비교적 작은 데이터인 master 테이블을, right에 주문정보와 같은 detail 테이블을 둬야 함
728x90
'DataBase > Data & SQL' 카테고리의 다른 글
[Data] 로그(Log) 데이터의 개념과 활용, 사례 및 수집 알아보기 (0) | 2023.04.06 |
---|---|
[Data] 데이터의 종류, 서비스 데이터와 행동 데이터(로그성 데이터) (0) | 2023.04.05 |
[Data] 데이터 관리, 마스터 데이터와 MDM(Master Data Management) (0) | 2023.02.12 |
[SQL] SQL 성능확인, Query Plan 보는 법 (Oracle, MySQL) (1) | 2023.01.31 |
[MySQL] 바이너리 로그(binlog)란? (0) | 2023.01.19 |
댓글