ORACLE CONCATERNATION
from
1. ORACLE CONCATERNATION
CONCATERNATION 은 OR 연산의 효율적인 이용을 위해 사용된다. A라는 테이블이 있고 이에 대해 B, C라는 조건이 OR 로 있을 때 B,C 조건이 같은 컬럼에 대한 조건이면 FULL SCAN 이 나타날 확률이 높아진다. B,C 라는 조건이 결합인덱스로 묶여 있는 경우에는 INDEX FULL SCAN 을 할 가능성이 높다. 하지만 CONCATERNATION 이 일어나면 OR 로 묶여 있는 각 조건에 대하여 각각의 조건을 만족하는 합집합을 구한다. 표현하자면
(A=B) U (A=C) 이런 느낌이다. 이는 다시 말해 중복값이 제거된다는 이야기다.
장점은 위와 같이 처리했을 때 효율적인 엑세스(인덱스 등을 이용한)가 가능한 상황일 때 이며 단점은 오브젝트를 중복 접근한다는 것이다.
힌트의 사용방법은 OR 를 사용한 쿼리에서 /*+ use_concat */ 힌트를 사용한다.
CONCATERNATION 으로 풀리면 나타나는 특징이 있다. 그것은 술어부가 마지막 술어부에서 WHERE 절 술어부 방향으로 체크된다는 것이다.
2. CONCATERNATION 예제
select /*+ use_concat */first_name,salary,department_id
from employees
where department_id >80
or (department_id = 80 and salary > 10000)
or salary > 12000
/
위의 쿼리를 수행하면 총 20건이 나오며 실행플랜은 아래와 같다.
Execution Plan
----------------------------------------------------------
Plan hash value: 3551705692
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 73 | 1022 | 8 (0)| 00:00:01 |
| 1 | CONCATENATION | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 11 | 154 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 11 | | 1 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL | EMPLOYEES | 20 | 280 | 3 (0)| 00:00:01 |
|* 5 | TABLE ACCESS FULL | EMPLOYEES | 42 | 588 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("DEPARTMENT_ID">80)
4 - filter("DEPARTMENT_ID"=80 AND "SALARY">10000 AND LNNVL("DEPARTMENT_ID">80))
5 - filter("SALARY">12000 AND (LNNVL("DEPARTMENT_ID"=80) OR LNNVL("SALARY">10000)) AND
LNNVL("DEPARTMENT_ID">80))
위의 술어부 정보를 보면 5 -> 4 -> 3 순으로 사용되었음을 알 수 있다. 술어부를 보면 LNNVL 이 있는데 이에 대한 설명은 생략하겠다. (오라클이 내부적으로 사용하는 함수이며
UNKNOWN 이나 FALSE 일 때 TRUE 가 되는 함수이다. 이가 의미하바는 LNNVL 에 정의 되어 있는 집합군을 제거한다느 것이다. 이는 UNION을 사용한 것과 동일하다 : 중복값제거)
위의 값이 중복값제거한 결과라는 것은 아래의 쿼리를 수행해 확인할 수 있다.
select count(*) from
(select * from employees where department_id >80
union all
select * from employees where department_id = 80 and salary > 10000
union all
select * from employees where salary > 12000)
/
COUNT(*)
----------
25
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | | |
| 2 | VIEW | | 321 | | 2 (0)| 00:00:01 |
| 3 | UNION-ALL PARTITION| | | | | |
|* 4 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 11 | 33 | 1 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | EMP_IX2 | 22 | 154 | 1 (0)| 00:00:01 |
|* 6 | INDEX FULL SCAN | EMP_IX2 | 59 | 236 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
select count(*) from
(select * from employees where department_id >80
union
select * from employees where department_id = 80 and salary > 10000
union
select * from employees where salary > 12000)
/
COUNT(*)
----------
20
-----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 11 (28)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | | |
| 2 | VIEW | | 92 | | 11 (28)| 00:00:01 |
| 3 | SORT UNIQUE | | 92 | 6256 | 11 (82)| 00:00:01 |
| 4 | UNION-ALL | | | | | |
| 5 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 11 | 748 | 2 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 11 | | 1 (0)| 00:00:01 |
|* 7 | TABLE ACCESS FULL | EMPLOYEES | 22 | 1496 | 3 (0)| 00:00:01 |
|* 8 | TABLE ACCESS FULL | EMPLOYEES | 59 | 4012 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------
위에서의 20건은 OR 를 사용했을 때와 동일함을 알 수 있다.