Oracle 최적화 기 (RBO 와 CBO)
28412 단어 Oracle 데이터베이스Oacle최적화 하 다.sql
Oracle
의 최적화 기 는 두 가지 가 있 는데 규칙 을 바탕 으로 하 는 최적화 기 RBO
와 대 가 를 바탕 으로 하 는 최적화 기 CBO
가 있다.8i 이전에
Oracle
는 RBO
Rule Based Optimizer
SQL
, 규칙 을 바탕 으로 하 는 최적화 기) 를 사용 했다. 그의 집행 은 매우 간단 했다. 바로 최적화 기 에 15 개의 규칙 을 삽입 하고 SQL 문 구 를 실행 하 는 것 이 어떤 규칙 에 부합 되 는 지 규칙 에 따라 해당 하 는 Oracle
집행 계획 을 맞 추 는 것 이다.그 는 유행 이 지난 딱딱 한 최적화 기 였 기 때문에 10g 이후 버 전에 서 이미 차 였 다.8i 부터
CBO
도입 Cost Based Optimizer
Oracle
, 대 가 를 바탕 으로 하 는 최적화 기), 그의 사고방식 은 CBO
모든 집행 계획 에 관 한 정 보 를 얻 게 하고 이런 정 보 를 통 해 계산 분석 을 한 다음 에 대가 가 가장 적은 집행 계획 을 최종 집행 계획 으로 삼 는 것 이다.FIRST_ROWS(n)
최적화 기 는 두 가지 선택 할 수 있 는 운행 모드 가 있다.FIRST_ROWS(n)
ALL_ROWS
유 틸 리 티 모드 를 설정 할 때
Oracle
는 SQL
문 구 를 실행 할 때 결과 가 집 중 된 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 문 구 를 쓰 는 과정 에서 항상 최적화 기의 역할 을 고려 하 는 학습 방법 을 제공 했다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
자바 작업 은 Clob 또는 NClob 데이터 형식의 저장 프로 세 스 인 스 턴 스 를 포함 합 니 다.텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.