12.2 버전에서 Band Join 기능이 추가되었다. 오라클 문서에서 Band Join이라는 용어를 사용했지만 Sort Merge Join의 기능 개선으로 보인다. 관련 내용을 살펴보자.
테스트를 위해 아래와 같이 테이블을 생성하자.
-- 1 DROP TABLE t1 PURGE; CREATE TABLE t1 AS SELECT ROWNUM AS c1 FROM XMLTABLE ('1 to 10000');
아래는 12.1 버전에서 수행된 쿼리다. 9.13초가 소요되었다. 6번 SORT JOIN 오퍼레이션에서 PGA를 만번 스캔하여 5천만건(=10000*10000/2)의 데이터를 추출한 다음, 5번 FILTER 오퍼레이션에서 29,998건(=(10000*3)-2)을 남기고 모두 필터링했다. Predicate Information의 필터 조건("B"."C1">="A"."C1"-1)에서 PGA를 끝까지 스캔한 것을 확인할 수 있다.
-- 2 SELECT /*+ OPTIMIZER_FEATURES_ENABLE('12.1.0.2') */ a.c1, AVG (b.c1) AS ag FROM t1 a, t1 b WHERE b.c1 BETWEEN a.c1 - 1 AND a.c1 + 1 GROUP BY a.c1; ------------------------------------------------------------------------------- | Id | Operation | Name | Starts | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 10000 |00:00:09.13 | 56 | | 1 | HASH GROUP BY | | 1 | 10000 |00:00:09.13 | 56 | | 2 | MERGE JOIN | | 1 | 29998 |00:00:09.11 | 56 | | 3 | SORT JOIN | | 1 | 10000 |00:00:00.01 | 28 | | 4 | TABLE ACCESS FULL | T1 | 1 | 10000 |00:00:00.01 | 28 | |* 5 | FILTER | | 10000 | 29998 |00:00:09.10 | 28 | |* 6 | SORT JOIN | | 10000 | 50M|00:00:05.52 | 28 | | 7 | TABLE ACCESS FULL| T1 | 1 | 10000 |00:00:00.01 | 28 | ------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 5 - filter("B"."C1"<="A"."C1"+1) 6 - access("B"."C1">="A"."C1"-1) filter("B"."C1">="A"."C1"-1)
아래 쿼리는 12.2.0.1 버전에서 수행된 쿼리다. FILTER 오퍼레이션이 사라졌고 0.02초가 소요되었다. 5번 SORT JOIN 오퍼레이션에서 PGA를 만번 스캔하여 29,998건의 데이터를 추출했다. Predicate Information의 필터 조건에 "B"."C1"<="A"."C1"+1 조건이 추가되어 불필요한 범위에 대한 스캔이 사라진 것을 확인할 수 있다.
-- 3 SELECT /*+ OPTIMIZER_FEATURES_ENABLE('12.2.0.1') */ a.c1, AVG (b.c1) AS ag FROM t1 a, t1 b WHERE b.c1 BETWEEN a.c1 - 1 AND a.c1 + 1 GROUP BY a.c1; ------------------------------------------------------------------------------ | Id | Operation | Name | Starts | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 10000 |00:00:00.02 | 56 | | 1 | HASH GROUP BY | | 1 | 10000 |00:00:00.02 | 56 | | 2 | MERGE JOIN | | 1 | 29998 |00:00:00.01 | 56 | | 3 | SORT JOIN | | 1 | 10000 |00:00:00.01 | 28 | | 4 | TABLE ACCESS FULL| T1 | 1 | 10000 |00:00:00.01 | 28 | |* 5 | SORT JOIN | | 10000 | 29998 |00:00:00.01 | 28 | | 6 | TABLE ACCESS FULL| T1 | 1 | 10000 |00:00:00.01 | 28 | ------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 5 - access("B"."C1">="A"."C1"-1) filter(("B"."C1"<="A"."C1"+1 AND "B"."C1">="A"."C1"-1))
[2018-10-05]
잘못된 결과 값이 반환되는 버그가 보고되고 있다. 관련 파라미터는 아래와 같다.
NAME DEFAULT_VALUE DESCRIPTION -------------------------- ------------- -------------------------------------------------- _optimizer_band_join_aware TRUE enable the detection of band join by the optimizer
'Oracle > Tuning' 카테고리의 다른 글
HASH JOIN BUFFERED 오퍼레이션 (0) | 2018.06.20 |
---|---|
NVL 함수와 스칼라 서브 쿼리 (0) | 2018.06.15 |
TABLE ACCESS BY INDEX ROWID BATCHED 오퍼레이션 #1 (0) | 2018.03.09 |
Top-N 쿼리 개선 사례 (0) | 2018.03.07 |
인덱스와 DML 문 (0) | 2018.03.06 |