Oracle 최적화 기 (RBO 와 CBO)

Oracle 의 최적화 기 는 두 가지 가 있 는데 규칙 을 바탕 으로 하 는 최적화 기 RBO 와 대 가 를 바탕 으로 하 는 최적화 기 CBO 가 있다.
8i 이전에 OracleRBO Rule Based Optimizer SQL, 규칙 을 바탕 으로 하 는 최적화 기) 를 사용 했다. 그의 집행 은 매우 간단 했다. 바로 최적화 기 에 15 개의 규칙 을 삽입 하고 SQL 문 구 를 실행 하 는 것 이 어떤 규칙 에 부합 되 는 지 규칙 에 따라 해당 하 는 Oracle 집행 계획 을 맞 추 는 것 이다.그 는 유행 이 지난 딱딱 한 최적화 기 였 기 때문에 10g 이후 버 전에 서 이미 차 였 다.
8i 부터 CBO 도입 Cost Based Optimizer Oracle, 대 가 를 바탕 으로 하 는 최적화 기), 그의 사고방식 은 CBO 모든 집행 계획 에 관 한 정 보 를 얻 게 하고 이런 정 보 를 통 해 계산 분석 을 한 다음 에 대가 가 가장 적은 집행 계획 을 최종 집행 계획 으로 삼 는 것 이다.FIRST_ROWS(n) 최적화 기 는 두 가지 선택 할 수 있 는 운행 모드 가 있다.
FIRST_ROWS(n)
ALL_ROWS
유 틸 리 티 모드 를 설정 할 때 OracleSQL 문 구 를 실행 할 때 결과 가 집 중 된 n 개의 기록 을 가장 빠 른 속도 로 피드백 하 는 것 을 우선 고려 합 니 다. 다른 결 과 는 동료 피드백 이 필요 하지 않 습 니 다. 즉, 데 이 터 를 처리 할 때 뒤의 데 이 터 는 아직 추출 되 지 않 았 을 수도 있 고 앞의 데 이 터 는 사용자 에 게 되 돌 아 왔 습 니 다.이런 수 요 는 사이트 검색 이나 BBS 페이지 에서 자주 볼 수 있다.예 를 들 어 매번 조회 정보의 20 개 만 표시 할 때 설정 FIRST_ROWS(20) 이 매우 적합 하 다.페이지 나 누 기 작업 에 있어 서 는 앞 페이지 일수 록 결 과 를 표시 하 는 데 걸 리 는 시간 이 짧 습 니 다.
다음은 전형 적 인 페이지 의 예 를 들 어 보 겠 습 니 다.
idle> select /*+first_rows(10)*/ b.x,b.y

2 from (select /*+first_rows(10)*/ a.*,rownum

3 from (select /*+first_rows(10)*/ from t order by x) a

4 where rownum<=20) b

5 where rownum>=10;

주의해 야 할 것 은 정렬 에 사용 되 는 X 색인 이 있어 야 합 니 다. 그렇지 않 으 면 CBO 무시 하고 사용 할 수 있 습 니 다 FIRST_ROWS(n).ALL_ROWS 모델 이 CBO 일 때 우리 가 ALL_ROWS 가장 빠 른 속도 로 Oracle 를 집행 하고 결과 집 을 모두 되 돌려 야 한 다 는 것 을 의미한다.그것 과 SQL 의 차 이 는 FIRST_ROWS(n) 전체적인 집행 효율 을 강조 하고 ALL_ROWS 가장 빠 른 속도 로 n 조 기록 으로 돌아 가 는 것 을 강조 하 는 것 이다.FIRST_ROWS(n) ALL_ROWS 시스템 에서 많이 사용 되 는데 그 목적 은 실행 결과 의 마지막 기록 을 신속하게 얻 는 데 있다.
아래 문장 을 통 해 수정 할 수 있다 OLAP
alter system set optimizer_mode=all_rows scope=both;

Oracle CBO 의 몇 가지 기본 적 인 조회 전환 에 대한 상세 한 설명
계획 을 수행 하 는 개발 과정 에서 전환 과 선택 은 서로 다른 임 무 를 가진다.실제로 한 조회 에서 문법 과 권한 검 사 를 마 친 후에 먼저 '조회 전환' 이 라 고 불 리 는 절차 가 발생 한다. 여기 서 일련의 조회 블록 전환 을 한 다음 에 '우선 선택' (최적화 기 는 최종 집행 계획 을 결정 하기 위해 서로 다른 계획 에 원 가 를 계산 하여 최종 집행 계획 을 선택한다).
우 리 는 조회 블록 이 optimizer_mode 키워드 로 구분 되 고 조회 의 작성 방식 은 조회 블록 간 의 관 계 를 결정 한 다 는 것 을 알 고 있다. 각 조회 블록 은 보통 다른 조회 블록 에 박 히 거나 특정한 방식 으로 연결 된다.예 를 들 면:
select * from employees where department_id in (select department_id from departments)

포 함 된 검색 블록 이지 만 검색 기법 을 바 꾸 면 더 좋 은 검색 계획 을 제공 할 수 있 는 지 탐색 하 는 것 이 목적 입 니 다.
이러한 조회 전환 절 차 는 실행 사용자 에 게 완전히 투명 하 다 고 할 수 있 습 니 다. 변환기 가 조회 결과 집합 을 바 꾸 지 않 고 SQL 구문 구 조 를 완전히 바 꿀 수 있다 는 것 을 알 아야 합 니 다. 따라서 우 리 는 자신의 조회 문장의 심리 적 기 대 를 재평가 할 필요 가 있 습 니 다. 비록 이러한 전환 은 일반적으로 좋 은 일이 지만 더욱 효율 적 인 실행 계획 을 얻 기 위해 서 입 니 다.
우 리 는 지금 몇 가지 기본 적 인 전환 에 대해 토론 합 시다.
1. 보기 통합 2. 하위 조회 내장 3. 서술 어 앞 밀어 4. 물 화 보기 조회 재 작성
보기 통합
이 방식 은 쉽게 이해 할 수 있 습 니 다. 내 장 된 보 기 를 독립 적 으로 처리 하 는 조회 블록 으로 펼 치 거나 나머지 부분 을 조회 하 는 것 과 합 쳐 하나의 실행 계획 으로 만 듭 니 다. 변 경 된 문 구 는 기본적으로 보 기 를 포함 하지 않 습 니 다.
보기 통합 은 보통 외부 조회 블록 에서 발생 하 는 술어 입 니 다.
1. 다른 검색 블록 의 색인 에서 사용 할 수 있 는 열 2. 다른 검색 블록 의 파 티 션 에서 사용 할 수 있 는 열 3. 연결 보기 에서 줄 수 를 되 돌려 주 는 조건 을 제한 할 수 있 습 니 다.
이러한 조회 기의 전환 에서 보 기 는 항상 자신의 하위 조회 계획 이 있 는 것 이 아니 라 미리 분석 되 고 일반적인 상황 에서 조회 의 다른 부분 과 합 쳐 성능 을 향상 시 킬 수 있 습 니 다. 다음 과 같 습 니 다.
SQL> set autotrace traceonly explain
--       
SQL> select * from EMPLOYEES a,
  2  (select DEPARTMENT_ID from EMPLOYEES) b_view
  3  where a.DEPARTMENT_ID = b_view.DEPARTMENT_ID(+)
  4  and a.SALARY > 3000;

Execution Plan
----------------------------------------------------------
Plan hash value: 1634680537

----------------------------------------------------------------------------------------
| Id  | Operation          | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                   |  3161 |   222K|     3   (0)| 00:00:01 |
|   1 |  NESTED LOOPS OUTER|                   |  3161 |   222K|     3   (0)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| EMPLOYEES         |   103 |  7107 |     3   (0)| 00:00:01 |
|*  3 |   INDEX RANGE SCAN | EMP_DEPARTMENT_IX |    31 |    93 |     0   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("A"."SALARY">3000)
   3 - access("A"."DEPARTMENT_ID"="DEPARTMENT_ID"(+))

--   NO_MERGE       
SQL> select * from EMPLOYEES a,
  2  (select /*+ NO_MERGE */DEPARTMENT_ID from EMPLOYEES) b_view
  3  where a.DEPARTMENT_ID = b_view.DEPARTMENT_ID(+)
  4  and a.SALARY > 3000;

Execution Plan
----------------------------------------------------------
Plan hash value: 1526679670

-----------------------------------------------------------------------------------
| Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |           |  3161 |   253K|     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN RIGHT OUTER|           |  3161 |   253K|     7  (15)| 00:00:01 |
|   2 |   VIEW                |           |   107 |  1391 |     3   (0)| 00:00:01 |
|   3 |    TABLE ACCESS FULL  | EMPLOYEES |   107 |   321 |     3   (0)| 00:00:01 |
|*  4 |   TABLE ACCESS FULL   | EMPLOYEES |   103 |  7107 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("A"."DEPARTMENT_ID"="B_VIEW"."DEPARTMENT_ID"(+))
   4 - filter("A"."SALARY">3000)

어떤 경우 에는 보기 통합 이 금지 되 거나 제 한 될 수 있 습 니 다. 한 조회 블록 에 분석 함수, 취 합 함수, 집합 연산 (예 를 들 어 유 니 온, intersect, minux), orderby 자구, 그리고 rownum 의 모든 것 을 사용 하면 이러한 상황 이 발생 합 니 다.그럼 에 도 불구 하고 우 리 는 / + MERGE (v) / 힌트 를 사용 하여 보기 통합 을 강제 할 수 있 습 니 다. 단, 돌아 오 는 결과 집합 이 일치 하 는 것 을 전제 로 해 야 합 니 다!!다음 예:
SQL> set autotrace on
--       avg        
SQL> SELECT e1.last_name, e1.salary, v.avg_salary
  2  FROM hr.employees e1,
  3  (SELECT department_id, avg(salary) avg_salary
  4  FROM hr.employees e2
  5  GROUP BY department_id) v
  6  WHERE e1.department_id = v.department_id AND e1.salary > v.avg_salary;

Execution Plan
----------------------------------------------------------
Plan hash value: 2695105989

----------------------------------------------------------------------------------
| Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |           |    17 |   697 |     8  (25)| 00:00:01 |
|*  1 |  HASH JOIN           |           |    17 |   697 |     8  (25)| 00:00:01 |
|   2 |   VIEW               |           |    11 |   286 |     4  (25)| 00:00:01 |
|   3 |    HASH GROUP BY     |           |    11 |    77 |     4  (25)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| EMPLOYEES |   107 |   749 |     3   (0)| 00:00:01 |
|   5 |   TABLE ACCESS FULL  | EMPLOYEES |   107 |  1605 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("E1"."DEPARTMENT_ID"="V"."DEPARTMENT_ID")
       filter("E1"."SALARY">"V"."AVG_SALARY")

--  /*+ MERGE(v) */        
SQL> SELECT /*+ MERGE(v) */ e1.last_name, e1.salary, v.avg_salary
  2  FROM hr.employees e1,
  3  (SELECT department_id, avg(salary) avg_salary
  4  FROM hr.employees e2
  5  GROUP BY department_id) v
  6  WHERE e1.department_id = v.department_id AND e1.salary > v.avg_salary;

Execution Plan
----------------------------------------------------------
Plan hash value: 3553954154

----------------------------------------------------------------------------------
| Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |           |   165 |  5610 |     8  (25)| 00:00:01 |
|*  1 |  FILTER              |           |       |       |            |          |
|   2 |   HASH GROUP BY      |           |   165 |  5610 |     8  (25)| 00:00:01 |
|*  3 |    HASH JOIN         |           |  3296 |   109K|     7  (15)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| EMPLOYEES |   107 |  2889 |     3   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL| EMPLOYEES |   107 |   749 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------

2. 하위 조회 내장
가장 전형 적 인 것 은 하위 조회 가 표 연결 로 바 뀌 었 다 는 것 이다. 보기 와 합 쳐 진 주요 차이 점 은 하위 조회 가 where 자구 에 있 고 변환기 에 의 해 포 함 된 검 사 를 하 는 것 이다.
다음은 하위 조회 = = > 표 연결 의 예 입 니 다.
SQL> select employee_id, last_name, salary, department_id
  2  from hr.employees
  3  where department_id in
  4  (select department_id
  5  from hr.departments where location_id > 1700);

Execution Plan
----------------------------------------------------------
Plan hash value: 432925905

---------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                   |    34 |   884 |     4   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                 |                   |       |       |            |          |
|   2 |   NESTED LOOPS                |                   |    34 |   884 |     4   (0)| 00:00:01 |
|   3 |    TABLE ACCESS BY INDEX ROWID| DEPARTMENTS       |     4 |    28 |     2   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN          | DEPT_LOCATION_IX  |     4 |       |     1   (0)| 00:00:01 |
|*  5 |    INDEX RANGE SCAN           | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |
|   6 |   TABLE ACCESS BY INDEX ROWID | EMPLOYEES         |    10 |   190 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("LOCATION_ID">1700)
   5 - access("DEPARTMENT_ID"="DEPARTMENT_ID")

--   /*+ NO_UNNEST */              
SQL> select employee_id, last_name, salary, department_id
  2  from hr.employees
  3  where department_id in
  4  (select /*+ NO_UNNEST */department_id
  5  from hr.departments where location_id > 1700);

Execution Plan
----------------------------------------------------------
Plan hash value: 4233807898

--------------------------------------------------------------------------------------------
| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |             |    10 |   190 |    14   (0)| 00:00:01 |
|*  1 |  FILTER                      |             |       |       |            |          |
|   2 |   TABLE ACCESS FULL          | EMPLOYEES   |   107 |  2033 |     3   (0)| 00:00:01 |
|*  3 |   TABLE ACCESS BY INDEX ROWID| DEPARTMENTS |     1 |     7 |     1   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN         | DEPT_ID_PK  |     1 |       |     0   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter( EXISTS (SELECT /*+ NO_UNNEST */ 0 FROM "HR"."DEPARTMENTS"
              "DEPARTMENTS" WHERE "DEPARTMENT_ID"=:B1 AND "LOCATION_ID">1700))
   3 - filter("LOCATION_ID">1700)
   4 - access("DEPARTMENT_ID"=:B1)

하위 검색 어 를 실행 하지 않 고 포 함 된 검색 어 는 FILTER 를 사용 하여 두 장의 표 만 일치 하 는 것 을 볼 수 있 습 니 다. 서술 어 정보의 첫 번 째 검색 도 변경 되 지 않 았 습 니 다. 이것 은 EMPLOYEES 표 에서 돌아 오 는 107 줄 의 모든 줄 에 대해 하위 검색 을 실행 해 야 한 다 는 것 을 의미 합 니 다.Oacle 에 하위 조회 캐 시 최적화 가 존재 하지만 우 리 는 이 두 가지 계획 의 우열 을 판단 할 수 없 지만 NESTED LOOPS 에 비해 FILTER 연산 의 열 세 는 매우 뚜렷 하 다.
관련 하위 조 회 를 포함 하면, 끼 워 넣 기 과정 은 일반적으로 관련 하위 조 회 를 비 끼 워 넣 기 보기 로 변환 한 다음, 주 조회 의 표 x 와 연 결 됩 니 다. 예 를 들 어:
SQL> select outer.employee_id, outer.last_name, outer.salary, outer.department_id
  2  from hr.employees outer
  3  where outer.salary >
  4  (select avg(inner.salary)
  5  from hr.employees inner
  6  where inner.department_id = outer.department_id);

Execution Plan
----------------------------------------------------------
Plan hash value: 2167610409

----------------------------------------------------------------------------------
| Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |           |    17 |   765 |     8  (25)| 00:00:01 |
|*  1 |  HASH JOIN           |           |    17 |   765 |     8  (25)| 00:00:01 |
|   2 |   VIEW               | VW_SQ_1   |    11 |   286 |     4  (25)| 00:00:01 |
|   3 |    HASH GROUP BY     |           |    11 |    77 |     4  (25)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| EMPLOYEES |   107 |   749 |     3   (0)| 00:00:01 |
|   5 |   TABLE ACCESS FULL  | EMPLOYEES |   107 |  2033 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("ITEM_1"="OUTER"."DEPARTMENT_ID")
       filter("OUTER"."SALARY">"AVG(INNER.SALARY)")

위의 조 회 는 하위 조 회 를 보기 로 바 꾸 어 주 조회 와 hash join 을 진행 하 는 것 입 니 다. 변 경 된 조 회 는 다음 과 같 습 니 다.
SQL> select outer.employee_id, outer.last_name, outer.salary, outer.department_id
  2  from hr.employees outer,
  3  (select department_id,avg(salary) avg_sal from hr.employees group by department_id) inner
  4  where inner.department_id = outer.department_id and outer.salary > inner.avg_sal;

사실 이 두 문장의 집행 계획 도 일치한다.
술어
서술 어 를 내부 검색 블록 에서 통합 할 수 없 는 검색 블록 으로 추진 하면 서술 어 조건 이 더욱 일찍 선택 되 고 필요 하지 않 은 데이터 줄 을 일찍 걸 러 내 효율 을 높 일 수 있 으 며 이러한 방식 으로 일부 색인 을 사용 할 수 있 습 니 다.
--       
SQL> set autotrace traceonly explain
SQL> SELECT e1.last_name, e1.salary, v.avg_salary
  2  FROM hr.employees e1,
  3  (SELECT department_id, avg(salary) avg_salary
  4  FROM hr.employees e2
  5  GROUP BY department_id) v
  6  WHERE e1.department_id = v.department_id
  7  AND e1.salary > v.avg_salary
  8  AND e1.department_id = 60;

Execution Plan
----------------------------------------------------------
Plan hash value: 3521487559

-----------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |                   |     1 |    41 |     3   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                   |                   |       |       |            |          |
|   2 |   NESTED LOOPS                  |                   |     1 |    41 |     3   (0)| 00:00:01 |
|   3 |    VIEW                         |                   |     1 |    26 |     2   (0)| 00:00:01 |
|   4 |     HASH GROUP BY               |                   |     1 |     7 |     2   (0)| 00:00:01 |
|   5 |      TABLE ACCESS BY INDEX ROWID| EMPLOYEES         |     5 |    35 |     2   (0)| 00:00:01 |
|*  6 |       INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |     5 |       |     1   (0)| 00:00:01 |
|*  7 |    INDEX RANGE SCAN             | EMP_DEPARTMENT_IX |     5 |       |     0   (0)| 00:00:01 |
|*  8 |   TABLE ACCESS BY INDEX ROWID   | EMPLOYEES         |     1 |    15 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   6 - access("DEPARTMENT_ID"=60)
   7 - access("E1"."DEPARTMENT_ID"=60)
   8 - filter("E1"."SALARY">"V"."AVG_SALARY")

--        
SQL> SELECT e1.last_name, e1.salary, v.avg_salary
  2  FROM hr.employees e1,
  3  (SELECT department_id, avg(salary) avg_salary
  4  FROM hr.employees e2
  5  WHERE rownum > 1 -- rownum       no_merge no_push_pred  ,               
  6  GROUP BY department_id) v
  7  WHERE e1.department_id = v.department_id
  8  AND e1.salary > v.avg_salary
  9  AND e1.department_id = 60;

Execution Plan
----------------------------------------------------------
Plan hash value: 3834222907

--------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                   |     3 |   123 |     7  (29)| 00:00:01 |
|*  1 |  HASH JOIN                   |                   |     3 |   123 |     7  (29)| 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| EMPLOYEES         |     5 |    75 |     2   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |     5 |       |     1   (0)| 00:00:01 |
|*  4 |   VIEW                       |                   |    11 |   286 |     4  (25)| 00:00:01 |
|   5 |    HASH GROUP BY             |                   |    11 |    77 |     4  (25)| 00:00:01 |
|   6 |     COUNT                    |                   |       |       |            |          |
|*  7 |      FILTER                  |                   |       |       |            |          |
|   8 |       TABLE ACCESS FULL      | EMPLOYEES         |   107 |   749 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("E1"."DEPARTMENT_ID"="V"."DEPARTMENT_ID")
       filter("E1"."SALARY">"V"."AVG_SALARY")
   3 - access("E1"."DEPARTMENT_ID"=60)
   4 - filter("V"."DEPARTMENT_ID"=60)
   7 - filter(ROWNUM>1)

위의 두 조 회 를 비교 해 보면 첫 번 째 조회 에서 DEPARTMENTID = 60 서술 어 는 보기 v 에 추진 되 어 실 행 됩 니 다. 그러면 내부 보기 조 회 는 부서 번호 가 60 인 평균 월급 만 받 으 면 됩 니 다.두 번 째 조회 에 서 는 각 부서 의 평균 임금 을 계산 한 후 외부 조회 와 연결 할 때 DEPARTMENT 를 사용 해 야 한다.ID = 60 조건 여과, 상대 적 으로 서술 어 조건 을 기다 리 기 위해 더 많은 작업 을 했 습 니 다.
4. 물 화 된 보 기 를 사용 하여 조회 재 작성
물 화 된 보기 로 조회 재 작성 기능 을 열 때 CBO 유 틸 리 티 는 해당 조회 가 기본 표 와 물 화 된 보기 에 대한 접근 원 가 를 평가 합 니 다. 유 틸 리 티 가 이 조회 결 과 를 물 화 된 보기 에서 얻 는 것 이 더 효율 적 이 라 고 판단 하면 자동 으로 물 화 된 보기 로 선택 하여 실 행 됩 니 다. 그렇지 않 으 면 기본 표 에 대한 조회 계획 을 생 성 합 니 다.
아니면 밤 을 보 러 올 까?
SQL> set autotrace traceonly explain
SQL> select DEPARTMENT_ID,count(EMPLOYEE_ID) from EMPLOYEES group by DEPARTMENT_ID;

Execution Plan
----------------------------------------------------------
Plan hash value: 1192169904

--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |    11 |    33 |     4  (25)| 00:00:01 |
|   1 |  HASH GROUP BY     |           |    11 |    33 |     4  (25)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| EMPLOYEES |   107 |   321 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

--         
SQL> create materialized view log on EMPLOYEES with sequence,
  2  rowid (EMPLOYEE_ID,DEPARTMENT_ID) including new values;

Materialized view log created.

--       ,         
SQL> create materialized view mv_t
  2  build immediate refresh fast on commit
  3  enable query rewrite as
  4  select DEPARTMENT_ID,count(EMPLOYEE_ID) from EMPLOYEES group by DEPARTMENT_ID;

Materialized view created.

SQL> select DEPARTMENT_ID,count(EMPLOYEE_ID) from EMPLOYEES group by DEPARTMENT_ID;

Execution Plan
----------------------------------------------------------
Plan hash value: 1712400360

-------------------------------------------------------------------------------------
| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |      |    12 |   312 |     3   (0)| 00:00:01 |
|   1 |  MAT_VIEW REWRITE ACCESS FULL| MV_T |    12 |   312 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement (level=2)

두 번 째 조회 에서 볼 수 있 습 니 다. 지정 한 조회 EMPLOYEES 표 이지 만 유 틸 리 티 는 자동 으로 물 화 된 보기 의 실행 경 로 를 선택 하 였 습 니 다. 물 화 된 보기 가 현재 조회 에 필요 한 결과 집합 데 이 터 를 기록 한 것 으로 판단 되 기 때문에 물 화 된 보 기 를 직접 방문 하면 더욱 효율 적 입 니 다.
주의해 야 할 것 은 이곳 의 물 화 된 보기 조회 재 작성 은 자동 으로 발생 하 는 것 이 며, 마찬가지 로 SELECT 알림 방식 으로 조회 재 작성 을 강제 할 수도 있다 는 점 이다.
요약:
비록 최적화 기 는 사용자 가 투명 한 상황 에서 우리 의 조회 구 조 를 바 꾸 었 지만 일반적인 상황 에서 이것 은 /*+ rewrite(mv_t) */ 최적화 모델 을 바탕 으로 판단 이 비교적 효율 적 인 선택 이다. 이것 은 우리 가 기대 하 는 것 이자 우리 에 게 SQL 문 구 를 쓰 는 과정 에서 항상 최적화 기의 역할 을 고려 하 는 학습 방법 을 제공 했다.

좋은 웹페이지 즐겨찾기