클라우드 데이터베이스 Oracle 12c 가이드 (2016년)
옵티마이저 관련 신규 기능 0 0 12,230

by 구루비스터디 옵티마이저 Oracle12c Adaptive Plan Adaptive Statisitcs [2023.09.05]


옵티마이저 관련 신규 기능

적응적인 쿼리 최적화(Adaptive Query Optimization)

  • AQQ는 실행계획을 런타임 실행 시에 조정하고 또한 향후에 더 나은 실행 계획을 생성하기 위해 옵티마이저에 도움을 주는 추가 메타데이터를 수집하는 오라클 데이터베이스 기능 집합
  • Adaptive Plan(적응적인 계획)
  • Adaptive Statistic(적응적인 통계 정보)

Adaptive Plan

  • SQL이 실행되는 동안 Statistics Collector가 수집된 통계정보를 기반으로 실행계획을 수정 후 다음 번 쿼리 실행시에 사용

12.1.0.0.2에서는 (NL <-> HASH), 병렬 조인 쿼리에서의 분배 방법(Broadcast, Range , Hash, Hybrid)에 대해서만 관여


Adaptive Plan의 구조

  • Adaptive Plan은 Join이 포함된 SQL에서만 생성된다.
  • SQL문을 파싱하고 해당 SQL문에 대한 실행계획을 생성.
  • 동시에 Adaptive Plan에 대한 자격이 된다면 추가적인 Sub Plan을 생성
  • 이런 SubPlan은 Plan에 삽입되는 통계 수집기 세트와 연관된다.
  • Statistics Collector가 일정량의 데이터를 버퍼링해서 분석하고 이를 기존의 테이블과 컬럼 통계 메타데이터와 일치하는지 여부를 확인한다.
  • 내부적으로 정의된 임계 값을 기준으로 통계 수집기가 런타임 실행 시에 사용될 수 있는 SubPlan을 결정한다.
  • 이 SubPlan과 관련된 실행 계획과 통계 수집기가 함께 나중에 사용하기 위해 커서에 저장된다.
  • 오라클은 SQL 실행시 원래의 Plan으로 실행하고, 이 계획을 실행할 때 통계 수집기에 의해서 샘플 데이터가 수집되고 버퍼링 되고 분석된다.
  • 샘플링된 로우가 미리 계산된 통계 임계치(예를 들어 Cardinality가 비정상적으로 치우쳤다면(Skew)되었다면)를 크게 벗어난다면 대안실행 계획으로 원래 계획을 바꾼다.
  • 실행계획은 쿼리의 실행이나 쿼리의 다음 번 실행 동안 동적으로 변경 할 수 있다.

Statistics Collector는 Adaptive Plan 사용 시에 옵티마이저에 의해서 생성되는 Row Source Operation의 일종이다. 최초 Plan 생성 시에 삽입되고 로우 버퍼링, 통계 정보 비교, 대안 PLAN 결정을 수행한다.


Adaptive Plan 사용 설정

  • OPTIMIZERFEATUREENABLE : 12.1.0.0.1 이상으로 설정
  • OPTIMIZERADAPTIVEREPORTING_ONLY : Adaptive Plan을 사용하기 위해서는 FALSE로 설정.

Adaptive Plan 조회

  • dbms_xplan.display_cursor를 이용하여 조회 가능
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'all +note +adaptive'));

SQL>  select substr(sql_text, 1, 50), is_resolved_adaptive_plan from v$sql
   2  where is_resolved_adaptive_plan = 'Y'


SUBSTR(SQL_TEXT,1,50)                                                                                I
---------------------------------------------------------------------------------------------------- -
SELECT /*+ CONNECT_BY_FILTERING */ s.privilege# FR                                                   Y
SELECT COUNT(*) FROM DBA_SCHEDULER_WINDOWS A, DBA_                                                   Y

-- is_resolved_adaptive_plan 컬럼을 통해 SQL문이 기존의 계획인 Adaptive Plan인지를 파악하는데 도움 될 수 있음

조인방법

SQL> create table testing_p(id number, the_value varchar2(30));
SQL> create index ix_testingP on testing_p(id);

SQL> create table testing_c(id_p number, id_t number, another_value varchar2(30));
SQL> create index ix_testingC_01 on testing_c(id_p);
SQL> create index ix_testingC_02 on testing_c(id_t);
SQL> create index ix_testingC_03 on testing_c(id_p, id_t);

SQL> select a.table_name, a.index_name, b.num_rows table_rows, a.num_rows index_rows
  2  from user_indexes a, user_tables b
  3  where a.table_name = b.table_name
  4  and a.table_name  like 'TESTING%';

TABLE_NAME                     INDEX_NAME                     TABLE_ROWS INDEX_ROWS
------------------------------ ------------------------------ ---------- ----------
TESTING_C                      IX_TESTINGC_02                                     0
TESTING_C                      IX_TESTINGC_03                                     0
TESTING_C                      IX_TESTINGC_01                                     0
TESTING_P                      IX_TESTINGP                                        0

SQL> select count(*)
  2  from (
  3  select b.id_t, b.id_p, b.another_value
  4  from testing_P a, testing_c b
  5  where a.id = b.id_p and a.id between 10001 and 10003);


SQL> select * from table(dbms_xplan.display_cursor(null, null, 'all +note +adaptive'));


--------------------------------------------------------------------------
| Id  | Operation          | Name           | Rows  | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                |       |       |     1 (100)|
|   1 |  SORT AGGREGATE    |                |     1 |    26 |            |
|   2 |   NESTED LOOPS     |                |     1 |    26 |     0   (0)|
|*  3 |    INDEX RANGE SCAN| IX_TESTINGP    |     1 |    13 |     0   (0)|
|*  4 |    INDEX RANGE SCAN| IX_TESTINGC_01 |     1 |    13 |     0   (0)|
--------------------------------------------------------------------------

-----
   - dynamic statistics used: dynamic sampling (level=2)

-- 통계 정보를 수행하지 않은 상태에서 data insert
SQL> truncate table testing_p;
SQL> truncate table testing_c;

SQL> declare
  2  begin
  3  for tt in 1..1000 loop
  4   insert into testing_p values(tt, 'www.testing.com');
  5   commit;
  6  end loop;
  7  for tt in 1..1000 loop
  8   insert into testing_p values(10001, 'www.testing.com');
  9   commit;
 10  end loop;
 11  end;
 12  /

SQL> declare
  2  begin
  3  for aa in (select id from testing_p)
  4  loop for zz in 1..3 loop
  5   insert into testing_c values(aa.id, zz, 'www.testing.com');
  6  end loop;
  7  end loop;
  8  commit;
  9  
 10  for zz in 4..1000
 11  loop
 12   insert into testing_c values(1001, zz, 'www.testing.com');
 13  end loop;
 14  commit;
 15  end;
 16  /


SQL> select count(*)
  2  from (
  3  select b.id_t, b.id_p, b.another_value
  4  from testing_P a, testing_c b
  5  where a.id = b.id_p and a.id between 10001 and 10003);


SQL> select * from table(dbms_xplan.display_cursor(null, null, 'all +note +adaptive'));


--------------------------------------------------------------------------
| Id  | Operation          | Name           | Rows  | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                |       |       |     1 (100)|
|   1 |  SORT AGGREGATE    |                |     1 |    26 |            |
|   2 |   NESTED LOOPS     |                |     1 |    26 |     0   (0)|
|*  3 |    INDEX RANGE SCAN| IX_TESTINGP    |     1 |    13 |     0   (0)|
|*  4 |    INDEX RANGE SCAN| IX_TESTINGC_01 |     1 |    13 |     0   (0)|
--------------------------------------------------------------------------

-----
   - dynamic statistics used: dynamic sampling (level=2)


-- 통계 정보를 수행하지 않은 상태에서 data insert
SQL> truncate table testing_p;
SQL> truncate table testing_c;

SQL> declare
  2  begin
  3  for tt in 1..1000 loop
  4   insert into testing_p values(tt, 'www.testing.com');
  5   commit;
  6  end loop;
  7  for tt in 1..1000 loop
  8   insert into testing_p values(10001, 'www.testing.com');
  9   commit;
 10  end loop;
 11  end;
 12  /

SQL> declare
  2  begin
  3  for aa in (select id from testing_p)
  4  loop for zz in 1..3 loop
  5   insert into testing_c values(aa.id, zz, 'www.testing.com');
  6  end loop;
  7  end loop;
  8  commit;
  9  
 10  for zz in 4..1000
 11  loop
 12   insert into testing_c values(1001, zz, 'www.testing.com');
 13  end loop;
 14  commit;
 15  end;
 16  /


SQL> select count(*)
  2  from (
  3  select b.id_t, b.id_p, b.another_value
  4  from testing_P a, testing_c b
  5  where a.id = b.id_p and a.id between 10001 and 10003);


SQL> select * from table(dbms_xplan.display_cursor(null, null, 'all +note +adaptive'));


--------------------------------------------------------------------------
| Id  | Operation          | Name           | Rows  | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                |       |       |     1 (100)|
|   1 |  SORT AGGREGATE    |                |     1 |    26 |            |
|   2 |   NESTED LOOPS     |                |     1 |    26 |     0   (0)|
|*  3 |    INDEX RANGE SCAN| IX_TESTINGP    |     1 |    13 |     0   (0)|
|*  4 |    INDEX RANGE SCAN| IX_TESTINGC_01 |     1 |    13 |     0   (0)|
--------------------------------------------------------------------------

-----
   - dynamic statistics used: dynamic sampling (level=2)


  • Adaptive Plan은 테이블이 통계 수집이 되지 않았다면 나타나지 않는다. 통계가 오래 되었거나 빈 테이블이거나 Current 상태이거나 상관없이 통계 정보가 존재하는지 유무가 중요 하다.
  • AUTOTRACE에서 "-": 붙은 라인은 inactive 한 로우다. 이 대시 마크는 실행 계획상의 이 로우가 고려는 됐지만 최적이 아니라서 사용되지 않은 Sub Plan임을 나타낸다.
  • 4번 라인에서 Statistics Collector가 실행된 것이 표시된다. Statistics Collector는 로우를 버퍼링하고 이를 분석해서실행 계획에서 어떤 액세스 방법이 최적인지를 결정한다.
SQL> exec dbms_stats.gather_table_stats('GHLEE', 'TESTING_P', CASCADE => TRUE);
SQL> exec dbms_stats.gather_table_stats('GHLEE', 'TESTING_C', CASCADE => TRUE);



SQL> SET AUTOTRACE ON
SQL> select count(*)
  2  from (
  3  select b.id_t, b.id_p, b.another_value
  4  from testing_P a, testing_c b
  5  where a.id = b.id_p and a.id between 10001 and 10003);

  COUNT(*)
----------
   3000000

Elapsed: 00:00:00.24

Execution Plan
----------------------------------------------------------

--------------------------------------------------------------------------------
| Id  | Operation                | Name           | Rows  | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |                |     1 |    10 |    22  (55)|
|   1 |  SORT AGGREGATE          |                |     1 |    10 |            |
|*  2 |   HASH JOIN              |                |  3000K|    28M|    22  (55)|
|   3 |    NESTED LOOPS          |                |  3000K|    28M|    22  (55)|
|   4 |     STATISTICS COLLECTOR |                |       |       |            |
|*  5 |      INDEX RANGE SCAN    | IX_TESTINGP    |  1000 |  5000 |     3   (0)|
|*  6 |     INDEX RANGE SCAN     | IX_TESTINGC_01 |  3000 | 15000 |     7   (0)|
|*  7 |    INDEX FAST FULL SCAN  | IX_TESTINGC_01 |  3000 | 15000 |     7   (0)|
--------------------------------------------------------------------------------
Note
-----
   - 'PLAN_TABLE' is old version

* 원래 위에서  "This is an Adaptive Plan"이라는 정보가 표시되어야 하는데, 안나옴


SQL> select count(*)
  2  from (
  3  select b.id_t, b.id_p, b.another_value
  4  from testing_P a, testing_c b
  5  where a.id = b.id_p and a.id between 10001 and 10003);


SQL> select * from table(dbms_xplan.display_cursor(null, null, 'all +note +adaptive'));


---------------------------------------------------------------------------------------------
|   Id  | Operation                | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|     0 | SELECT STATEMENT         |                |       |       |    22 (100)|          |
|     1 |  SORT AGGREGATE          |                |     1 |    10 |            |          |
|  *  2 |   HASH JOIN              |                |  3000K|    28M|    22  (55)| 00:00:01 |
|-    3 |    NESTED LOOPS          |                |  3000K|    28M|    22  (55)| 00:00:01 |
|-    4 |     STATISTICS COLLECTOR |                |       |       |            |          |
|  *  5 |      INDEX RANGE SCAN    | IX_TESTINGP    |  1000 |  5000 |     3   (0)| 00:00:01 |
|- *  6 |     INDEX RANGE SCAN     | IX_TESTINGC_01 |  3000 | 15000 |     7   (0)| 00:00:01 |
|  *  7 |    INDEX FAST FULL SCAN  | IX_TESTINGC_01 |  3000 | 15000 |     7   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

Note
-----
   - statistics feedback used for this statement
   - this is an adaptive plan (rows marked '-' are inactive)

{code:xml}
SQL> exec dbms_stats.gather_table_stats('GHLEE', 'TESTING_P', CASCADE => TRUE);
SQL> exec dbms_stats.gather_table_stats('GHLEE', 'TESTING_C', CASCADE => TRUE);



SQL> SET AUTOTRACE ON
SQL> select count(*)
  2  from (
  3  select b.id_t, b.id_p, b.another_value
  4  from testing_P a, testing_c b
  5  where a.id = b.id_p and a.id between 10001 and 10003);

  COUNT(*)
----------
   3000000

Elapsed: 00:00:00.24



--------------------------------------------------------------------------------
| Id  | Operation                | Name           | Rows  | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |                |     1 |    10 |    22  (55)|
|   1 |  SORT AGGREGATE          |                |     1 |    10 |            |
|*  2 |   HASH JOIN              |                |  3000K|    28M|    22  (55)|
|   3 |    NESTED LOOPS          |                |  3000K|    28M|    22  (55)|
|   4 |     STATISTICS COLLECTOR |                |       |       |            |
|*  5 |      INDEX RANGE SCAN    | IX_TESTINGP    |  1000 |  5000 |     3   (0)|
|*  6 |     INDEX RANGE SCAN     | IX_TESTINGC_01 |  3000 | 15000 |     7   (0)|
|*  7 |    INDEX FAST FULL SCAN  | IX_TESTINGC_01 |  3000 | 15000 |     7   (0)|
--------------------------------------------------------------------------------
Note
-----
   - 'PLAN_TABLE' is old version

* 원래 위에서  "This is an Adaptive Plan"이라는 정보가 표시되어야 하는데, 안나옴


SQL> select count(*)
  2  from (
  3  select b.id_t, b.id_p, b.another_value
  4  from testing_P a, testing_c b
  5  where a.id = b.id_p and a.id between 10001 and 10003);


SQL> select * from table(dbms_xplan.display_cursor(null, null, 'all +note +adaptive'));

---------------------------------------------------------------------------------------------
|   Id  | Operation                | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|     0 | SELECT STATEMENT         |                |       |       |    22 (100)|          |
|     1 |  SORT AGGREGATE          |                |     1 |    10 |            |          |
|  *  2 |   HASH JOIN              |                |  3000K|    28M|    22  (55)| 00:00:01 |
|-    3 |    NESTED LOOPS          |                |  3000K|    28M|    22  (55)| 00:00:01 |
|-    4 |     STATISTICS COLLECTOR |                |       |       |            |          |
|  *  5 |      INDEX RANGE SCAN    | IX_TESTINGP    |  1000 |  5000 |     3   (0)| 00:00:01 |
|- *  6 |     INDEX RANGE SCAN     | IX_TESTINGC_01 |  3000 | 15000 |     7   (0)| 00:00:01 |
|  *  7 |    INDEX FAST FULL SCAN  | IX_TESTINGC_01 |  3000 | 15000 |     7   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

Note
-----
   - statistics feedback used for this statement
   - this is an adaptive plan (rows marked '-' are inactive)

병렬분배방법

  • 옵티마이저가 가장 적절한 분배 방법을 충분히 판단하지 못하는 경우 Hybrid hash Distiribution Technique라는 분배 방법을 사용 할 수 있다.
  • 이 기능을 사용하기로 선택했다면 실행 시점까지 사용할 분배 방법을 결정하지 않는다.
  • 실행 계획을 생성하고 옵티마이저는 작업의 생산자 측의 병렬 서버 프로세스의 앞 쪽에 통계 수집기를 삽입한다.
  • Default로 실행계획이 hash broadcast 분배 방식을 사용하지만 로우의 개수가 병렬도 DOP의 2배보다 작다면 실행 계획은 쿼리에서 Broadcast 분배 방식으로 전환된다.
SQL> select count(*) from
  2  (select /*+ parallel(4) full(a) full(b) */
  3  b.id_t, b.id_p, b.another_value
  4  from testing_p a, testing_c b
  5  where a.id = b.id_p
  6  and a.id between 10001 and 10003);


----------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name      | Rows  | Bytes | Cost (%CPU)|    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |           |     1 |    10 |     8  (38)|        |      |            |
|   1 |  SORT AGGREGATE                  |           |     1 |    10 |            |        |      |            |
|   2 |   PX COORDINATOR                 |           |       |       |            |        |      |            |
|   3 |    PX SEND QC (RANDOM)           | :TQ10002  |     1 |    10 |            |  Q1,02 | P->S | QC (RAND)  |
|   4 |     SORT AGGREGATE               |           |     1 |    10 |            |  Q1,02 | PCWP |            |
|*  5 |      HASH JOIN                   |           |  3000K|    28M|     8  (38)|  Q1,02 | PCWP |            |
|   6 |       PX RECEIVE                 |           |  1000 |  5000 |     2   (0)|  Q1,02 | PCWP |            |
|   7 |        PX SEND HYBRID HASH       | :TQ10000  |  1000 |  5000 |     2   (0)|  Q1,00 | P->P | HYBRID HASH|
|   8 |         STATISTICS COLLECTOR     |           |       |       |            |  Q1,00 | PCWC |            |
|   9 |          PX BLOCK ITERATOR       |           |  1000 |  5000 |     2   (0)|  Q1,00 | PCWC |            |
|* 10 |           TABLE ACCESS FULL      | TESTING_P |  1000 |  5000 |     2   (0)|  Q1,00 | PCWP |            |
|  11 |       PX RECEIVE                 |           |  3000 | 15000 |     3   (0)|  Q1,02 | PCWP |            |
|  12 |        PX SEND HYBRID HASH (SKEW)| :TQ10001  |  3000 | 15000 |     3   (0)|  Q1,01 | P->P | HYBRID HASH|
|  13 |         PX BLOCK ITERATOR        |           |  3000 | 15000 |     3   (0)|  Q1,01 | PCWC |            |
|* 14 |          TABLE ACCESS FULL       | TESTING_C |  3000 | 15000 |     3   (0)|  Q1,01 | PCWP |            |
----------------------------------------------------------------------------------------------------------------



Adaptive Statisitcs

  • 옵티마이저가 더 나은 실행계획을 생성할 수 있도록 도움을 주기 위해 기존 기능을 업그레이드한 새로운 기능이 추가 되었다.
  • Automatic Repotimization(통계 피드백 Statistics Feedback))
  • SQL Plan Directive
  • Dynamic Staitistics 개선 사항

Automatic Reoptimization

  • Adaptive Plan은 비효율적인 조인 순서는 차선의 실행 계획이 생성될 가능성이 높아 진다.
  • SQL문이 실행될 때마다 옵티마이저는 문장이 실행하는 동안에 수집된 통계 정보를 검토 한다.
  • 실행 계획이 생성될 때 사용된 통계 정보와 수집된 통게를 비교해서 만약 통계 정보가 차이가 난다면 옵티마이저는 다음 실행을 위해 대안 계획을 생성한다.
  • 이 Reoptimization 작업은 커서 캐시에서 해당 쿼리가 있는 동안에 여러 번 발생할 수 있다.
Reoptimization의 두 가지 유형
  • 통계 피드백(Statistics Feedback)
  • 이전에는 카디널리티 피드백이라고 알려져 있다. 기본적으로 카디널리티의 부정확한 예측 문제가 발생하는 실행 계획을 개선시키다.
  • 특정 SQL문에 의해 반환된 로우를 모니터링하고 그 실행 계획을 생성할 때 계산된 예측값과 비교 한다.
  • 예측값이 너무 차이가 나면 옵티마이저는 다음 번에 사용하기 위해 실제로 수집된 데이터를 저장한다.
  • 11g 에서는 이러한 통계는 커서로 저장되어 Aging Out 될 수 있었다. 12c는 옵티마이저의 SQL Plan Directive에 저장한다.
  • 현재는 수집된 통계의 부분으로 조인 통계가 포함되어 있다.
  • 바인드 변수를 사용한 쿼리의 성능을 향상시키기 위해 Adaptive Cursor Sharing과 같이 작동할 수 있다.
  • V$SQL의 IS_REOPTIMIZABLE이라는 컬림 추가되어 Reoptimization 여부를 확인할 수 있다.
  • 성능 피드백(performance Feedback)
  • 병렬 쿼리를 최적화 하는데 사용된다.
  • PARALLEL_DEGREE_POLICY 파라미터를 ADAPTIVE로 설정하면 옵티마이저가 쿼리가 병렬로 실행되어야 하고 이를 선택했다면 쿼리에서 사용되는 병렬도의 값을 결정하는 설정이다.
  • 쿼리가 실행하면 데이터베이스는 쿼리의 성능을 모니터링 한다.
  • 쿼리가 첫 번째 실행을 완료한 후 옵티마이저는 초기에 선택한 dop와 명령문 실행 동안 수집된 다양한 성능 통계를 기반으로 계산된 DOP를 비교한다.
  • 값이 차이가 나는 경우 데이터베이스는 나중에 재파싱을 위해서 문장에 표시를 해두고 피드백이라는 정보로서 실행동안 수집된 통계를 저장한다.
  • 나중에 문장이 파싱할 때 피드백이 사용되고 새로운 DOP 가 계산된다.

SQL Plan Directive

  • 기타 SQL 문의 더 나은 최적화를 위해 옵티마이저에서 추가적인 정보를 제공하는 쿼리의 표현 레벨에서 제공하는 기능이다.
  • 비슷한 WHERE 조건을 가진 여러 개의 다른 SQL문이 단일 쿼리에서 생성된 SQL PLAN Directive의 이점을 누릴 수 있다.
  • SQL문이 실행할 때 옵티마이저는 쿼리에서 리턴되는 실제의 카?널리티값과 실행 계획 생성 시 계산한 예상 카디널리티를 비교한다.
  • 이 실제의 정보는 SQL Plan Directive에 저장된다.
  • 초기에는 SQL Plan Directive는 커서 캐시에 저장되었지만 주기적으로 SYSAUX 테이블 스페이스로 내려써서 저장된다.
  • DBMS_SPD.FLUSH_SQL_PLAN_DIRECTIVE는 메모리에서 영구적인 스토리지로 내려 쓸 수 있다.
  • 내려 쓰지 않으면 Directive는 데이터 Dictionary View에서 볼수 없다.
  • 수고 SQL 문을 컴파일 하는 동안 옵티마이저는 쿼리와 SQL Plan Directive를 검토해서 누락된 확장 통계나 히스토그램이 있는지를 확인한다.
  • 이 누락된 통계나 히스토그램을 일단 기록해두고 나중에 이를 수집한다.
  • 생성된 Directive가 추가 통계를 필요로 하는 경우 옵티마이저는 이러한 통계를 수집하기 위해 Dynamic Sampling을 사용한다.
  • SQL Plan Directive는 컬럼 그룹이 통계 수집이 필요한지를 판다하는 데 도움이 되는 정보로서 옵티마이저에게 제공된다.
  • 만일 SQL Plan Directive가 특정한 컬럼의 집합이 컬럼 그룹으로 생성되고 통계 수집 할 필요가 있다라고 표시된 경우에 옵티마이저는 자동으로 이 작업을 수행한다.
  • 오라클 데이터베이스에서는 SQL Plan Directive를 이 정보가 더 이상 필요하지 않는 특정한 상황(통계 정보의 재수집 등)이 발생할 때까지 계속해서 이 정보를 사용한다.
  • 자동으로 오라클 데이터베이스에 의해 관리 된다.
  • 특정 SQL Plan Directive가 53주 동안 사용되지 않으면 이를 삭제 한다.
  • DBMS_APD.DROP_SQL_PLAN_DIRECTIVE 프로시저를 사용해서 SQL PLAN Directive를 삭제 할 수 있다.
"구루비 데이터베이스 스터디모임" 에서 2016년에 "클라우드 데이터베이스 Oracle 12c 가이드" 도서를 스터디하면서 정리한 내용 입니다.

- 강좌 URL : http://www.gurubee.net/lecture/4269

- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^

- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입