실행계획 SQL 연산(HASH JOIN)
Hash Join은 테이블의 조인 시 특정 테이블 하나(크기가 작은 테이블)를 메모리로 로드 후 Hash 기법을 이용하여 조건에 맞는 데이터를 추출하는 로우(ROW) 연산 또는 집합(SET) 연산 입니다.
일반적으로 Hash Join이 Merge Join 보다 성능이 우수하므로 힌트(USE_HASH)를 이용하여 인위적으로 해시 조인이 일어나도록 하는 것이 유리 합니다.
SQL문 사용시 인위적으로 Hash Join이 일어나게 하기 위해서는 USE_HASH 라는 힌트를 사용하면 되는데 힌트를 사용하지 않더라도 Join시 두 테이블 중 한 테이블이 상당히 작아 메모리에 로드 될만한 공간이 있다면 Hsah Join이 일어나는 실행 계획을 만들어 낼 수 있습니다.
SQL> SELECT /*+ ORDERED USE_HASH(DEPT, EMP) */
EMP.ENAME,
EMP.SAL,
DEPT.DNAME
FROM DEPT, EMP
WHERE DEPT.DEPTNO = EMP.DEPTNO;
Execution Plan
-----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE(Cost=5 Card=80 Bytes=8888)
1 0 HASH JOIN(Cost=5 Card=80 Bytes=8888)
2 1 TABLE ACCESS (FULL) OF ‘DEPT’ (Cost=1 Card=67 Bytes=3456)
3 1 TABLE ACCESS (FULL) OF ‘EMP’ (Cost=1 Card=90 Bytes=8756)
위 실행계획에서 DEPT 테이블이 위쪽에 위치하는데 보통 작은 테이블이 위에 위치할 때 좋은 성능을 낼 수 있습니다. 즉 DEPT 테이블이 메모리에 로드 되면 Oracle은 해싱 함수를 이용하여 EMP 테이블의 ROW들을 메모리에 로드 되어 있는 값과 비교하여 원하는 데이터를 추출 하며 이때 FROM절 뒤의 테이블 순서와 USE_HASH 힌트에 나오는 테이블의 순서는 같아야 합니다.
일반적으로 USE_HASH 힌트는 ORDERED 힌트와 같이 사용되는데 이때는 USE_HASH 인수로 두번째 테이블명(Alias 명)만을 적어도 됩니다. 즉 아래처럼 말입니다.
/*+ ORDERED USE_HASH(DEPT) */
Hash Join의 성능에 영향을 주는 파라미터는 HASH_AREA_SIZE와 HAHS_MULTIBLOCK_IO_COUNT가 있으며 첫번째 파라미터는 해시 조인 시 해시 테이블을 생성하기 위해 사용 가능한 메모리의 사이즈 이며 두번째 파라미터는 한번의 I/O로 해시 조인 시 쓰거나 읽을 수 있는 블록의 수입니다.(9i 이상에서는 HASH_MULTIBLOCK_IO_COUNT 파라미터는 더 이상 사용되지 않습니다.)
2017년 4월 17일 월요일
(구로디지털단지,IT실무,오라클강좌,자바강좌,Oracle Hint) 실행계획 SQL 연산(FILTER)
실행계획 SQL 연산(FILTER)
FILTER 연산은 데이터 추출 시 필터링이 일어나고 있음을 알려주는 SQL ROW 연산인데 WHERE 조건 절에서 인덱스를 사용하지 못할 때 발생하는 것입니다. NESTED LOOP 방식으로 해석할 수 있습니다.
아래의 예는 EMP TABLE에서 부서의 최소 급여를 받는 사람들을 추출하는 것입니다.
SQL>SELECT ENAME, SAL, JOB
FROM EMP A
WHERE SAL = (SELECT MIN(SAL)
FROM EMP B
WHERE B.DEPTNO = A.DEPTNO);
Execution Plan
---------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 FILTER
2 1 TABLE ACCESS (FULL) OF ‘EMP’
3 2 SORT (AGGREGATE)
4 3 TABLE ACCESS (BY INDEX ROWID) OF ‘EMP’
5 4 INDEX (RANGE SCAN) OF ‘idx_emp_deptno’ (NON-UNIQUE)
FILTER 연산은 데이터 추출 시 필터링이 일어나고 있음을 알려주는 SQL ROW 연산인데 WHERE 조건 절에서 인덱스를 사용하지 못할 때 발생하는 것입니다. NESTED LOOP 방식으로 해석할 수 있습니다.
아래의 예는 EMP TABLE에서 부서의 최소 급여를 받는 사람들을 추출하는 것입니다.
SQL>SELECT ENAME, SAL, JOB
FROM EMP A
WHERE SAL = (SELECT MIN(SAL)
FROM EMP B
WHERE B.DEPTNO = A.DEPTNO);
Execution Plan
---------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 FILTER
2 1 TABLE ACCESS (FULL) OF ‘EMP’
3 2 SORT (AGGREGATE)
4 3 TABLE ACCESS (BY INDEX ROWID) OF ‘EMP’
5 4 INDEX (RANGE SCAN) OF ‘idx_emp_deptno’ (NON-UNIQUE)
(구로디지털단지,IT실무,오라클강좌,자바강좌,Oracle Hint) 실행계획 SQL 연산(COUNT STOPKEY)
실행계획 SQL 연산(COUNT STOPKEY)
COUNT STOPKEY연산은 PSEUDO COLUMNS(의사 컬럼)이 WHERE절에 나타날 때 실행계획에 나타나는 SQL 연산 입니다.
SQL> SELECT EMPNO,
ENAME,
SAL
FROM EMP
WHERE ROWNUM < 10;
Execution Plan
---------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 COUNT(STOPKEY)
2 1 TABLE ACCESS (FULL) OF ‘EMP’
COUNT STOPKEY연산은 PSEUDO COLUMNS(의사 컬럼)이 WHERE절에 나타날 때 실행계획에 나타나는 SQL 연산 입니다.
SQL> SELECT EMPNO,
ENAME,
SAL
FROM EMP
WHERE ROWNUM < 10;
Execution Plan
---------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 COUNT(STOPKEY)
2 1 TABLE ACCESS (FULL) OF ‘EMP’
(구로디지털단지,IT실무,오라클강좌,자바강좌,Oracle Hint) 실행계획 SQL 연산(COUNT)
실행계획 SQL 연산(COUNT)
COUNT 연산은 PSEUDO COLUMNS(의사 컬럼)이 WHERE절이 아닌 SELECT 문장에 나타날 때 실행계획에 나타나는 SQL 연산 입니다.
SQL> SELECT ROWNUM,
EMPNO,
ENAME,
SAL
FROM EMP;
Execution Plan
---------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 COUNT
2 1 TABLE ACCESS (FULL) OF ‘EMP’
COUNT 연산은 PSEUDO COLUMNS(의사 컬럼)이 WHERE절이 아닌 SELECT 문장에 나타날 때 실행계획에 나타나는 SQL 연산 입니다.
SQL> SELECT ROWNUM,
EMPNO,
ENAME,
SAL
FROM EMP;
Execution Plan
---------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 COUNT
2 1 TABLE ACCESS (FULL) OF ‘EMP’
(구로디지털단지,IT실무,오라클강좌,자바강좌,Oracle Hint) 실행계획 SQL 연산(CONCATENATION)
실행계획 SQL 연산(CONCATENATION)
반환된 로우를 합산하는 연산 입니다. 아래의 예를 보죠…
SQL>SELECT *
FROM EMP
WHERE JOB=’SALESMAN’
AND DEPTNO IN (20, 40);
Execution Plan
-------------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 CONCATENATION
2 1 TABLE ACCESS (BY INDEX ROWID) OF ‘EMP’
3 2 AND-EQUAL
4 3 INDEX (RANGE SCAN) OF ‘idx_emp_deptno’ (NON-UNIQUE)
5 3 INDEX (RANGE SCAN) OF ‘idx_emp_job’ (NON-UNIQUE)
6 1 TABLE ACCESS (BY INDEX ROWID) OF ‘EMP’
7 6 AND-EQUAL
8 7 INDEX (RANGE SCAN) OF ‘idx_emp_deptno’ (NON-UNIQUE)
9 7 INDEX (RANGE SCAN) OF ‘idx_emp_job’ (NON-UNIQUE)
위의 실행 결과를 보면 JOB이 ‘SALESMAN’ 이면서 DEPTNO가 20인 데이터(AND-EQUAL)를 인덱스를 이용하여 추출하며 JOB이 ‘SALESMAN’ 이면서 DEPTNO가 40 데이터를 추출하여 서로 합산하여 결과를 만들어 냄을 알 수 있습니다.
결국 위의 SQL을 다르게 풀어 쓰면 다음과 같은 실행 계획을 가진다고 할 수가 있습니다.
(성능이 똑같다…)
SQL> SELECT *
FROM EMP
WHERE (JOB=’SALESMAN’ AND DEPTNO = 20)
OR (JOB=’SALESMAN’ AND DEPTNO = 40)
반환된 로우를 합산하는 연산 입니다. 아래의 예를 보죠…
SQL>SELECT *
FROM EMP
WHERE JOB=’SALESMAN’
AND DEPTNO IN (20, 40);
Execution Plan
-------------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 CONCATENATION
2 1 TABLE ACCESS (BY INDEX ROWID) OF ‘EMP’
3 2 AND-EQUAL
4 3 INDEX (RANGE SCAN) OF ‘idx_emp_deptno’ (NON-UNIQUE)
5 3 INDEX (RANGE SCAN) OF ‘idx_emp_job’ (NON-UNIQUE)
6 1 TABLE ACCESS (BY INDEX ROWID) OF ‘EMP’
7 6 AND-EQUAL
8 7 INDEX (RANGE SCAN) OF ‘idx_emp_deptno’ (NON-UNIQUE)
9 7 INDEX (RANGE SCAN) OF ‘idx_emp_job’ (NON-UNIQUE)
위의 실행 결과를 보면 JOB이 ‘SALESMAN’ 이면서 DEPTNO가 20인 데이터(AND-EQUAL)를 인덱스를 이용하여 추출하며 JOB이 ‘SALESMAN’ 이면서 DEPTNO가 40 데이터를 추출하여 서로 합산하여 결과를 만들어 냄을 알 수 있습니다.
결국 위의 SQL을 다르게 풀어 쓰면 다음과 같은 실행 계획을 가진다고 할 수가 있습니다.
(성능이 똑같다…)
SQL> SELECT *
FROM EMP
WHERE (JOB=’SALESMAN’ AND DEPTNO = 20)
OR (JOB=’SALESMAN’ AND DEPTNO = 40)
피드 구독하기:
글 (Atom)