[SQL 성능개선하기]- NESTED LOOPS 조인

이동찬·2023년 1월 28일
0

SQL

목록 보기
19/22

NESTED LOOPS JOIN

  • 옵티마이저가 Driving Table을 결정함(Outer Table)
  • Driving Table이 아닌 테이블은 Driven Table로 지정함
    ->(Inner Table)이라고도 함
  • Driving Table의 각 row에 대해 이들이 추출될 때마다 Driven Table의 연관된 모든 row를 조인에 의해 액세스
  • 튜닝 포인트
    - 테이블 간 조인 횟수를 최소화 할 수 있도록 Driving Table을 ?
    -> 조인 순서제어
    - Driven Table의 연결고리 칼럼에 대한 인덱스 구성

따라서, driving에서 데이터를 먼저 읽어내면서 데이터를 하나식 읽을 때마다 순차적으로 driven table에 연결을 하면서 데이터를 읽어내는 연결방식이 된다. 그렇기 때문에, 두 테이블간 조인횟수를 최소화(Driving table 중요) 할 수 있는 것이 첫번째 튜닝 포인트이다. 연결되는 driven table은 연결 칼럼에 대한 인덱스가 사용되어야 한다.


NESTED LOOPS JOIN의 수행 절차

  • 위 쿼리의 ORDERED로 인해 테이블 a가 먼저 읽는 테이블로 선정이 된다.
  • USE_NL에 대한 힌트때문에 두 테이블간 연결방식이 NESTEDLOOP 조인이 되는 것이다.
  • 따라서 조인 순서상 테이블 A가 먼저 읽는 테이블이 되는 이상, WHERE절에 주어진 A에 color에 대한 조건을 통해서 index사용을 먼저하게 된다.
  • 테이블 a로부터 데이터를 읽어서 테이블 b로 연결을 바로 시도하게 되는 것이다. 이때 연결되는 b는 joinkey_b라는 것에 주어진 인덱스를 통해서 반드시 연결이 행해져야 한다.

  • 테이블 a로부터는 color에 대한 인덱스 사용을 통해서 테이블 a로 접근하고, 또한, b로 연결을 지을때는 테이블 a의 JOINKEY와 b의 JOINKEY를 통해서 =로 조인을 해나갈때 b의 주어진 JOINKEY_B에 대한 인덱스를 통해서 연결이 되고있다라고 볼 수 있다. 이 때 연결되는 b에 대해서 추출한 데이터를 통해 b에 주어진 size가 MEDIUM이 되는지 확인해서 그 조건을 만족시키면 추출이 되는것이고 만족이 안되면 추출이 되지 않는 것이다. 그리고 계속 반복해나간다.
  • 따라서, 테이블 A와 테이블 B간의 연결횟수는 곧 테이블 A로부터 읽는 데이터 수의 비례한다고 할 수 있다.
  • 그렇기에, 두 테이블간 연결 횟수를 최소화하기 위해서는 DRIVING TABLE을 잘 선택해야 한다.

NESTED LOOPS JOIN의 장단점

  1. 인덱스에 의한 랜덤 액세스에 기반하고 있기 때문에 대량의 데이터 처리 시 적합하지 않음
  2. Driving Table로는 테이블의 데이터가 적은 마스터 테이블이거나, where절 조건으로 적절하게 row를 제어할 수 있는것이어야 함
  3. Driven Table에는 조인을 위한 적절한 인덱스가 생성되어 있어야 함

Driving Table의 원리

  • 테이블간 조인순서가 어떻게 되어있느냐에 따라서, 테이블간 발생되는 연결횟수를 나타내는 그림이다.

조인 순서 제어 방법

  • 조인 순서 제어를 위한 힌트 사용
    /*+ORDERED*/
    -FROM절에 기술한 테이블 순서대로 제어
    /*+LEADING(table명)*/
    • 힌트 내에 제시한 테이블이 드라이빙으로 채택됨
  • ORDERED 힌트와 같이 사용할 경우 LEADING힌트는 무시된다.
  • 만약 위처럼 힌트를 사용할 수 없다면
    -> 뷰(view)활용
    - 보통 뷰를 통해서 데이터를 먼저 읽어낼 수 있고, 뷰로부터 데이터를 읽은 결과로 다음 테이블에 연결을 시도하게 된다면 조인 순서를 제어할 수 있는 방안이 된다.
    -> 서프레싱(suppressing)활용
    ->FROM 절의 테이블 순서 변경
    - RBO하에서 각 테이블에 대한 규칙이 동일할 때,
    FROM절로부터 멀리 있는 테이블부터 처리함
    - CBO에서는 이 방법은 의미가 없음

연결 고리에 대한 인덱스

  • 위의 그림은 테이블 A와 B를 조인을 맺고있다. 두 테이블 간 연결시 아용되는 컬럼은 NAME이라는 컬럼이다. 두 테이블 모두 다 인덱스에 NAME이 있다는 가정하이다.
  • 밑 그림은 테이블 A만 인덱스의 NAME이 있다.
  • 3번처럼 TABLE A가 DRIVING이 돼서 데이터를 읽는다고 할 때, B는 연결 컬럼 인덱스가 없는것으로 인해 DRIVING에서 매번 데이터를 읽고 연결을 시도할 때마다 FULL TABLE SCAN을 하게된다. 테이블 B에 대한 FULL SCAN은 A로 부터 데이터를 읽은 수만큼 연결을 하는 가운데 존재하는 FULL SCAN이다. 그렇기에, 결코 속도를 낼 수 없다.

  • 둘다 인덱스가 없다면 NL을 할수가 없다.

예제

  • 여기서 데이터가 제일많은 순서는 C > B > A로 검토가 된다.

실행결과

  • 첫번째 테이블이 C로 선택이 되었다.
  • 그 C가 B와 연결되어 있다.
  • 맨 끝에 A와 연결을 시도한다.
  • 지금 데이터가 가장많은 C테이블이 먼저 Driving이 되기에 데이터가 제일 적은 A가 먼저 DRIVING이 되어야한다

문제점에 대한 개요


수정문


튜닝결과

0개의 댓글

관련 채용 정보