Driving과 Driven은 일반적으로 주도하는 역할과 주도 당하는 역할을 의미한다. 기술적인 맥락에서 보면 다음과 같다.
- Driving : 시스템 또는 구조에서 주요 동작을 결정하거나 제어하는 주체를 의미한다.
- ex. 절차적 프로그래밍이나 명령형 프로그래밍에서 개발자가 프로그램의 흐름을 직접 제어(if - else 문 등을 사용하여 프로그램의 흐름을 직접 설계)하며 드라이빙 역할을 수행
- Driven : 시스템에서 외부 입력이나 특정 조건에 의해 동작하는 대상을 의미한다.
- ex. Event-Driven Architecture : 특정 이벤트가 발생하면 동작을 수행하는 시스템, 외부 요청에 의해 실행되는 구조로 드리븐 상태이다.
Database의 드라이빙과 드리븐은 무엇일까?
| Join 에서의 Driving 과 Driven
데이터베이스에서 Join 연산은 2개 이상의 테이블을 결합하여 데이터를 가져오는 작업이다.
이 과정에서 어떤 테이블이 Driving 테이블인지 어떤 테이블이 Driven 테이블인지 결정하는 쿼리 최적화의 중요한 부분이다.
일반적으로 작은 데이터 세트 또는 효율적인 인덱스가 있는 테이블이 Driving 테이블로 선택된다.
- Join 시 먼저 엑세스 되어 Access Path(접근 경로)를 주도하는 테이블이다.
Driven 테이블은 Driving 테이블에 의해 검색되는 테이블이다.
- Driving 테이블의 결과를 기준으로 필요한 데이터를 가져온다.
- 일반적으로 큰 데이터 세트나 Join의 대상이 되는 테이블이 Driven 테이블로 선택된다.
간단한 예시를 들어보면 다음과 같다.
1000만건의 데이터를 가진 A 테이블과 1000건의 데이터를 가진 B 테이블을 조인할 때 드라이빙 순서에 따라 성능의 차이가 크다고 한다.
- 1000만 건의 A 테이블을 먼저 Driving 하면 1000만 번을 반복하며 B 테이블을 탐색한다.
- 하지만, 1000 건의 B 테이블을 먼저 Driving 하면 1000 번의 A 테이블이 탐색된다.
따라서, 작업 대상이 되는 rows의 수가 적은 테이블부터 액세스 되어야 전체 탐색이 줄어든다는 것이다.
Driving, Driven의 결정 요인에 대해 조금 더 알아보면, 다음과 같다.
DBMS는 쿼리 실행 계획을 수립할 때 드라이빙 테이블과 드리븐 테이블을 결정하게 된다.
- 테이블 크기 : 작은 테이블이 Driving 테이블로 선택되는 경우가 많다.
- 인덱스 여부 : 인덱스가 있는 테이블을 Driven 테이블로 두면 Driving 테이블이 Driven 테이블에 의해 반복적으로 Full Scan 하지 않아 더 빠르다. 한 쪽에만 인덱스가 있다면 인덱스가 없는 테이블을 Driving 테이블로 하게 된다.
실제 실행 계획에서의 표현은 어떨까?
SQL의 실행 계획을 확인하면 드라이빙과 드리븐의 관계를 파악할 수 있다. 일반적으로 DBMS는 Nested Loop Join, Hash Join, 또는 Merge Join 과 같은 방식으로 두 테이블을 결합한다.
- Nested Loop Join : 한 테이블(Driving)을 읽고, 다른 테이블(Driven)을 반복적으로 검색한다.
- Driving 테이블의 각 행에 대해 Driven 테이블에서 매칭되는 행을 검색한다.
- 일반적으로 작은 Driving 테이블과 인덱스가 있는 Driven 테이블에서 효율적이다.
- Block Nested Loop Join : Driving 테이블의 데이터를 Join Buffer에 저장한다.
- Driving 테이블에서 조건에 맞는 데이터를 검색 후 Join 버퍼에 저장하고, Join 버퍼와 Driven 테이블의 데이터를 비교한다.
- Driven 테이블은 한 번의 Full Scan으로 데이터를 처리한다. Driven 테이블의 Full Scan 횟수를 줄여 성능을 개선하는 방식이다.
- Batched Key Access Join : 랜덤 액세스 비효율을 줄이고, Sequential 액세스를 수행한다.
- Driven 테이블에 필요한 데이터를 미리 에측하고 정렬된 상태로 담는 Random Buffer라는 개념이 도입된다.
- Driving 테이블에서 데이터를 Join Buffer에 적재한다.
- Driven 테이블에서 필요한 데이터를 예측하고 Random Buffer에 저장한다.
- Random Buffer에 데이터를 정렬된 상태로 담아 Sequential Access를 수행한다.
- Join Buffer와 Random Buffer 데이터를 비교한 후, 동일한 데이터가 있다고 판단되면 Driven 테이블의 데이터가 접근하고 결과를 조인하여 반환한다.
- 다중 범위 읽기로 Driven 테이블의 데이터를 미리 정렬하여 효율적인 읽기를 수행한다. 따라서, Driven 테이블의 랜덤 액세스를 줄이고 성능을 향상시킨다.
- Hash Join : Hash 테이블을 생성하여 조인, Driving 테이블의 데이터를 기준으로 Hash를 만들고, Driven 테이블의 데이터를 매핑한다.
- 해시 값을 생성하여 Join을 수행한다. Join 열에 인덱스가 필요 없으며, 동등 비교 연산에 적합하다.
- 각 테이블의 데이터를 해시값으로 변환하여 해시 값을 기반으로 내부 조인을 수행한다.
- 결과를 조인 버퍼에 저장한 후 반환하기 때문에 대용량 데이터 처리에 적합하다.
- 해시 값 생성에 시간이 소요되기 때문에 적은양의 데이터 조인에는 비효율적이다.
'🔍 CS > 데이터베이스' 카테고리의 다른 글
11/30 - TIL : MongoDB (0) | 2024.11.30 |
---|---|
11/27 - TIL : JDBC, MyBatis, Hibernate (3) | 2024.11.27 |
11/24 - TIL : NoSQL과 Redis (0) | 2024.11.24 |
동시성 제어하기 - 07. 읽기와 쓰기의 트레이드 오프 (0) | 2023.06.07 |
동시성 제어하기 - 04. 낙관적 락 (0) | 2023.06.07 |