본문 바로가기
Oracle/튜닝

Dynamic Sampling에 대한 개념 및 테스트

by 취미툰 2022. 12. 27.
반응형

Dynamic Sampling 이란?

옵티마이저의 능력을 향상시키기 위해 도입된 기능입니다.

통계정보가 존재하지 않을 경우에 Dynamic Sampling level에 따라 데이터블록들을 Sampling한 후 통계정보를 생성해 SQL문을 수행합니다.(CBO에서만 작동하면 RBO에서는 작동하지 않습니다)

12c부터는 Dynamic Statistics 로 이름이 변경되었습니다.

 

사용시기?

SQL문을 컴파일 하는 동안 옵티마이저는 통계정보가 실행계획을 생성하기에 충분한지 여부를 고려하여 Dynamic Sampling을 사용할지 말지 여부를 결정합니다.

쿼리에 있는 테이블 중 하나 이상에 통계가 없는 경우 Dynamic Sampling는 옵티마이저가 기본 통계정보를 수집합니다.

 

SQL문에 복잡한 표현식이 포함되어 있고, 확장된 통계를 사용할 수 없는 경우 Dynamic Sampling을 사용할 수 있습니다.

확장된 통계(Extended Statistics)는 11g부터 도입되었으며 옵티마이저가 복잡한 표현식에 대해 좋은 품질의 통계정보 추정치를 얻는 것을 돕는 기능입니다.

 

 

출처 : https://blogs.oracle.com/optimizer/post/dynamic-sampling-and-its-impact-on-the-optimizer

 

Dynamic sampling and its impact on the Optimizer

Dynamic sampling (DS) was introduced to improve the optimizer's ability to generate good execution plans. This feature was enhanced and renamed Dynamic Statistics in Oracle Database 12c. The most common misconception is that DS can be used as a substitute

blogs.oracle.com

 

관련 파라미터?

(병렬처리가 아닌) Serial SQL문의 경우 Dynamic Sampling level은 optimizer_dynamic_sampling 파라미터에 의해 제어되지만 12cR1 부터는 쿼리가 컴파일 될때 dynamic statistics(12c부터 이름이 바뀜. Dynamic sampling과 동일) 를 할수도 있습니다. 12c R1의 파라미터는 optimizer_adaptive_features, 12c R2의 파라미터는 optimizer_adaptive_statistics로 제어됩니다. 즉, 12c R1 이후에는 관련 파라미터를 TRUE로 설정하여 활성화된 경우 Dynamic Sampling이 사용됩니다.

 

DB 버전 파라미터이름 Default Value
Oracle Database 12c Release 1 optimizer_adaptive_features (OAF) TRUE
Oracle Database 12c Release 2 이상 optimizer_adaptive_statistics (OAS) FALSE

 

사용방법?

1.힌트로 적용하기

dynamic_sampling([적용할 테이블명 or alias] [level])형식으로 적용 가능합니다.

select /*+ dynamic_sampling(t1 1) */ count(*)
       from ds_test t1, ds_test t2
         where t1.id = t2.id
  		 and  t1.val like '%O%'

 

2.파라미터 변경 DDL로 적용하기

--세션 레벨
SQL> ALTER SESSION SET optimizer_dynamic_sampling = 0;


--시스템 레벨
SQL> ALTER SYSTEM SET optimizer_dynamic_sampling = 0;

 

dynamic sampling level?

 

 

레벨 언제 사용되는지 sample size
(blocks)
0 dynamic statistics 안쓰기 N/A
1 SQL문에서 하나 이상의 non-partitioned table에 통계가 없을때 32
2
(default)
SQL문에서 하나 이상의 table(partition 포함)에 통계가 없을때, 64
3 level2 기준을 충족하는 모든 SQL문 그리고 where 절을 사용하는 하나이상의 표현식이 있는 모든 SQL문 64
4 level3 기준을 충족하는 모든 SQL문 그리고 복잡한 술어를 포함하는 모든 SQL문. 동일한 테이블에 있는 AND 또는 OR 연산자 64
5 level4 기준을 충족하는 모든 SQL문 128
6 level4 기준을 충족하는 모든 SQL문 256
7 level4 기준을 충족하는 모든 SQL문 512
8 level4 기준을 충족하는 모든 SQL문 1024
9 level4 기준을 충족하는 모든 SQL문 4086
10 모든 SQL문 All Blocks
11 자동으로 dynamic sampling이 필요한지 여부를 결정 Automatically determined

 

테스트?

여러가지 쿼리를 조회하여 dynamic sampling이 발생하는 상황등에 대해 확인해보겠습니다.

 

1.테스트용 테이블 생성(DS_TEST) : 통계정보 삭제

--인덱스 생성시 자동으로 통계정보 수집하지 않는 파라미터 
alter session set "_optimizer_compute_index_stats" = false;

drop table DS_TEST purge;
 
 
CREATE TABLE DS_TEST
       AS
         SELECT ROWNUM                    AS id
       ,      DBMS_RANDOM.STRING('a',30)  AS val  --랜덤 문자30개
         FROM  DUAL
       CONNECT BY ROWNUM < 1000000;
       
       
 create index idx_ds_test_id on ds_test(id);
 
 
 --통계정보 삭제
  exec dbms_stats.delete_table_stats(user,'ds_test');

 

2,조회 후 실행계획 확인

조건절이 없는 쿼리는 예상(E-rows)와 실제 결과(A-rows)의 차이가 없습니다.

 

SQL> select /*+ gather_plan_statistics */ count(*) from ds_test;

COUNT(*)  
--------- 
   999999

1 rows selected.

SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
 
 
 
 SQL_ID  785ncdsanjw5u, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ count(*) from ds_test
 
Plan hash value: 3949147434
 
----------------------------------------------------------------------------------------
| Id  | Operation          | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |         |      1 |        |      1 |00:00:00.02 |    5689 |
|   1 |  SORT AGGREGATE    |         |      1 |      1 |      1 |00:00:00.02 |    5689 |
|   2 |   TABLE ACCESS FULL| DS_TEST |      1 |    999K|    999K|00:00:00.04 |    5689 |
----------------------------------------------------------------------------------------

===========================================================================================
tkprof

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.01       0.01          0       5689          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.01       0.02          0       5689          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 156
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=5689 pr=0 pw=0 time=18058 us starts=1)
    999999     999999     999999   TABLE ACCESS FULL DS_TEST (cr=5689 pr=0 pw=0 time=50051 us starts=1 cost=1577 size=0 card=999999)

 

 

3.조건절 추가해서 조회 후 실행계획 확인

간단한 조건절을 추가했을 때에도 예상(E-rows)와 실제 결과(A-rows)의 차이가 없습니다.

SQL> select /*+ gather_plan_statistics */ count(*) from ds_test
where val like '%B%';

COUNT(*)  
--------- 
   441676

1 rows selected.

SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
SQL_ID  7q6fcsbs75p1m, child number 1
-------------------------------------
select /*+ gather_plan_statistics */ count(*) from ds_test where val 
like '%B%'
 
Plan hash value: 3949147434
 
----------------------------------------------------------------------------------------
| Id  | Operation          | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |         |      1 |        |      1 |00:00:00.24 |    5689 |
|   1 |  SORT AGGREGATE    |         |      1 |      1 |      1 |00:00:00.24 |    5689 |
|*  2 |   TABLE ACCESS FULL| DS_TEST |      1 |    441K|    441K|00:00:00.23 |    5689 |
----------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - filter(("VAL" LIKE '%B%' AND "VAL" IS NOT NULL))
 
Note
-----
   - statistics feedback used for this statement
   
   
============================================================================================
tkprof

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.15       0.24          0       5689          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.15       0.24          0       5689          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 156
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=5689 pr=0 pw=0 time=242106 us starts=1)
    441676     441676     441676   TABLE ACCESS FULL DS_TEST (cr=5689 pr=0 pw=0 time=256800 us starts=1 cost=1583 size=1550000 card=50000)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       2        0.00          0.00
  SQL*Net message from client                     2       10.73         10.73

 

4.조건절 여러개 추가 후 실행계획 확인

조건절을 여러 개 추가했을때 예상(E-rows)와 실제 결과(A-rows)의 차이가 있었습니다.

1,000,000건 중 125건 (0.0000125%)로 예상했지만 실제로는 81,450건의 결과값이 나왔습니다.

SQL> select /*+ gather_plan_statistics */ count(*) from ds_test
where val like '%B%'
and   val like '%A%'
and   val like '%C%';

COUNT(*)  
--------- 
    81450
    
SQL_ID  b6dcx3a7z86ty, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ count(*) from ds_test where val 
like '%B%' and   val like '%A%' and   val like '%C%'
 
Plan hash value: 3949147434
 
----------------------------------------------------------------------------------------
| Id  | Operation          | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |         |      1 |        |      1 |00:00:00.35 |    5689 |
|   1 |  SORT AGGREGATE    |         |      1 |      1 |      1 |00:00:00.35 |    5689 |
|*  2 |   TABLE ACCESS FULL| DS_TEST |      1 |    125 |  81450 |00:00:00.32 |    5689 |
----------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - filter(("VAL" LIKE '%B%' AND "VAL" LIKE '%A%' AND "VAL" LIKE '%C%' AND 
              "VAL" IS NOT NULL AND "VAL" IS NOT NULL AND "VAL" IS NOT NULL))
              
=======================================================================================================
tkprof

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.22       0.34          0       5689          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.22       0.35          0       5689          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 156
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=5689 pr=0 pw=0 time=348234 us starts=1)
     81450      81450      81450   TABLE ACCESS FULL DS_TEST (cr=5689 pr=0 pw=0 time=317243 us starts=1 cost=1583 size=3875 card=125)

 

5.조인으로 쿼리 조회 후 실행계획 확인

조건절을 여러 개 추가했을때 예상(E-rows)와 실제 결과(A-rows)의 차이가 있었습니다.

1,000,000건 중 125건 (0.0000125%)로 예상했지만 실제로는 81,295건의 결과값이 나왔습니다.

SQL> select /*+ gather_plan_statistics */ count(*)
       from ds_test t1, ds_test t2
   where t1.id = t2.id
   and  t1.val like '%O%' and t1.val like '%A%' and t1.val like '%G%';

COUNT(*)  
--------- 
    81295

1 rows selected.


 select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
 
 
SQL_ID  f952a6h01zrm0, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ count(*)        from ds_test t1, 
ds_test t2    where t1.id = t2.id    and  t1.val like '%O%' and t1.val 
like '%A%' and t1.val like '%G%'
 
Plan hash value: 2992804329
 
------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                |      1 |        |      1 |00:00:00.56 |    7931 |       |       |          |
|   1 |  SORT AGGREGATE        |                |      1 |      1 |      1 |00:00:00.56 |    7931 |       |       |          |
|*  2 |   HASH JOIN            |                |      1 |    125 |  81008 |00:00:00.57 |    7931 |  5598K|  3200K| 4451K (0)|
|*  3 |    TABLE ACCESS FULL   | DS_TEST        |      1 |    125 |  81008 |00:00:00.36 |    5689 |       |       |          |
|   4 |    INDEX FAST FULL SCAN| IDX_DS_TEST_ID |      1 |      1 |    999K|00:00:00.10 |    2242 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("T1"."ID"="T2"."ID")
   3 - filter(("T1"."VAL" LIKE '%O%' AND "T1"."VAL" LIKE '%A%' AND "T1"."VAL" LIKE '%G%' AND "T1"."VAL" IS NOT NULL 
              AND "T1"."VAL" IS NOT NULL AND "T1"."VAL" IS NOT NULL))
 
Note
-----
   - this is an adaptive plan
   
=======================================================================================================
tkprof

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.35       0.55          0       7931          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.35       0.55          0       7931          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 156
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=7931 pr=0 pw=0 time=551500 us starts=1)
     81295      81295      81295   HASH JOIN  (cr=7931 pr=0 pw=0 time=548997 us starts=1 cost=1833 size=5125 card=125)
     81295      81295      81295    NESTED LOOPS  (cr=5689 pr=0 pw=0 time=362440 us starts=1 cost=1833 size=5125 card=125)
     81295      81295      81295     STATISTICS COLLECTOR  (cr=5689 pr=0 pw=0 time=355281 us starts=1)
     81295      81295      81295      TABLE ACCESS FULL DS_TEST (cr=5689 pr=0 pw=0 time=342620 us starts=1 cost=1583 size=4500 card=125)
         0          0          0     INDEX RANGE SCAN IDX_DS_TEST_ID (cr=0 pr=0 pw=0 time=0 us starts=0 cost=2 size=5 card=1)(object id 191055)
    999999     999999     999999    INDEX FAST FULL SCAN IDX_DS_TEST_ID (cr=2242 pr=0 pw=0 time=95912 us starts=1 cost=2 size=5 card=1)(object id 191055)

 

6.복잡한 SQL문 작성 후 실행계획 확인

조건절을 여러 개 추가했을때 예상(E-rows)와 실제 결과(A-rows)의 차이가 있었습니다.

1,000,000건 중 6건 (0.0000006%)로 예상했지만 실제로는 1.540건의 결과값이 나왔습니다.

SQL> select /*+ gather_plan_statistics */ 
count(*)
from ds_test t1, ds_test t2
   where t1.id = t2.id
   and t1.val in (select val from ds_test where val like '%Z')
   and  t1.val like '%O%' and t1.val like '%A%' and t1.val like '%G%';


SQL_ID  ba8p0hrzczjap, child number 0
-------------------------------------
select /*+ gather_plan_statistics */  count(*) from ds_test t1, ds_test 
t2    where t1.id = t2.id    and t1.val in (select val from ds_test 
where val like '%Z')    and  t1.val like '%O%' and t1.val like '%A%' 
and t1.val like '%G%'
 
Plan hash value: 2160968040
 
------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                |      1 |        |      1 |00:00:00.63 |   13619 |       |       |          |
|   1 |  SORT AGGREGATE        |                |      1 |      1 |      1 |00:00:00.63 |   13619 |       |       |          |
|*  2 |   HASH JOIN            |                |      1 |      1 |   1504 |00:00:00.60 |   13619 |  2401K|  2401K| 1337K (0)|
|*  3 |    HASH JOIN SEMI      |                |      1 |      1 |   1504 |00:00:00.45 |   11377 |  1152K|  1152K| 1358K (0)|
|*  4 |     TABLE ACCESS FULL  | DS_TEST        |      1 |      6 |   1504 |00:00:00.33 |    5689 |       |       |          |
|*  5 |     TABLE ACCESS FULL  | DS_TEST        |      1 |      6 |   1504 |00:00:00.10 |    5688 |       |       |          |
|   6 |    INDEX FAST FULL SCAN| IDX_DS_TEST_ID |      1 |      1 |    999K|00:00:00.10 |    2242 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("T1"."ID"="T2"."ID")
   3 - access("T1"."VAL"="VAL")
   4 - filter(("T1"."VAL" LIKE '%O%' AND "T1"."VAL" LIKE '%A%' AND "T1"."VAL" LIKE '%G%' AND "T1"."VAL" LIKE '%Z' AND 
              "T1"."VAL" IS NOT NULL AND "T1"."VAL" IS NOT NULL AND "T1"."VAL" IS NOT NULL AND "T1"."VAL" IS NOT NULL))
   5 - filter(("VAL" LIKE '%Z' AND "VAL" LIKE '%O%' AND "VAL" LIKE '%A%' AND "VAL" LIKE '%G%' AND "VAL" IS NOT NULL 
              AND "VAL" IS NOT NULL AND "VAL" IS NOT NULL AND "VAL" IS NOT NULL))
 
Note
-----
   - this is an adaptive plan
   
==============================================================================================================================
tkprof

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.40       0.63          0      13619          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.41       0.64          0      13619          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 156
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=13619 pr=0 pw=0 time=638191 us starts=1)
      1504       1504       1504   HASH JOIN  (cr=13619 pr=0 pw=0 time=612529 us starts=1 cost=3168 size=72 card=1)
      1504       1504       1504    NESTED LOOPS  (cr=11377 pr=0 pw=0 time=417013 us starts=1 cost=3168 size=72 card=1)
      1504       1504       1504     STATISTICS COLLECTOR  (cr=11377 pr=0 pw=0 time=416636 us starts=1)
      1504       1504       1504      HASH JOIN SEMI (cr=11377 pr=0 pw=0 time=448116 us starts=1 cost=3166 size=67 card=1)
      1504       1504       1504       TABLE ACCESS FULL DS_TEST (cr=5689 pr=0 pw=0 time=322781 us starts=1 cost=1583 size=216 card=6)
      1504       1504       1504       TABLE ACCESS FULL DS_TEST (cr=5688 pr=0 pw=0 time=99138 us starts=1 cost=1583 size=186 card=6)
         0          0          0     INDEX RANGE SCAN IDX_DS_TEST_ID (cr=0 pr=0 pw=0 time=0 us starts=0 cost=2 size=5 card=1)(object id 191055)
    999999     999999     999999    INDEX FAST FULL SCAN IDX_DS_TEST_ID (cr=2242 pr=0 pw=0 time=107052 us starts=1 cost=2 size=5 card=1)(object id 191055)

 

7. 5번과 동일한 쿼리지만 힌트로 dynamic sampling 4로 설정 후 쿼리 수행

dynamic sampling을 4로 주고 힌트를 확인결과 예상(E-rows)와 실제 결과(A-rows)의 차이가 거의 없이 나왔습니다.

1,000,000건 중 82,528건 (0.082528%)로 예상했지만 실제로는 81,295건의 결과값이 나왔습니다.

SQL> select /*+ gather_plan_statistics  dynamic_sampling(t1 4) */ count(*)
       from ds_test t1, ds_test t2
   where t1.id = t2.id
   and  t1.val like '%O%' and t1.val like '%A%' and t1.val like '%G%';

SQL_ID  cfz04438nt32b, child number 0
-------------------------------------
select /*+ gather_plan_statistics  dynamic_sampling(t1 4) */ count(*)   
     from ds_test t1, ds_test t2    where t1.id = t2.id    and  t1.val 
like '%O%' and t1.val like '%A%' and t1.val like '%G%'
 
Plan hash value: 2992804329
 
------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                |      1 |        |      1 |00:00:00.55 |    7931 |       |       |          |
|   1 |  SORT AGGREGATE        |                |      1 |      1 |      1 |00:00:00.55 |    7931 |       |       |          |
|*  2 |   HASH JOIN            |                |      1 |  82528 |  81295 |00:00:00.55 |    7931 |  5598K|  3200K| 4883K (0)|
|*  3 |    TABLE ACCESS FULL   | DS_TEST        |      1 |  82528 |  81295 |00:00:00.35 |    5689 |       |       |          |
|   4 |    INDEX FAST FULL SCAN| IDX_DS_TEST_ID |      1 |    999K|    999K|00:00:00.10 |    2242 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("T1"."ID"="T2"."ID")
   3 - filter(("T1"."VAL" LIKE '%O%' AND "T1"."VAL" LIKE '%A%' AND "T1"."VAL" LIKE '%G%' AND "T1"."VAL" IS NOT NULL 
              AND "T1"."VAL" IS NOT NULL AND "T1"."VAL" IS NOT NULL))
 
Note
-----
   - dynamic statistics used: dynamic sampling (level=0)
   - this is an adaptive plan
   
   
   
=============================================================================================================================
tkprof

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          3          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.35       0.56          0       7931          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.36       0.56          0       7934          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 156
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=7931 pr=0 pw=0 time=560622 us starts=1)
     81295      81295      81295   HASH JOIN  (cr=7931 pr=0 pw=0 time=562748 us starts=1 cost=3199 size=3383648 card=82528)
     81295      81295      81295    NESTED LOOPS  (cr=5689 pr=0 pw=0 time=367760 us starts=1 cost=3199 size=3383648 card=82528)
     81295      81295      81295     STATISTICS COLLECTOR  (cr=5689 pr=0 pw=0 time=358299 us starts=1)
     81295      81295      81295      TABLE ACCESS FULL DS_TEST (cr=5689 pr=0 pw=0 time=347722 us starts=1 cost=1583 size=2971008 card=82528)
         0          0          0     INDEX RANGE SCAN IDX_DS_TEST_ID (cr=0 pr=0 pw=0 time=0 us starts=0 cost=612 size=5 card=1)(object id 191055)
    999999     999999     999999    INDEX FAST FULL SCAN IDX_DS_TEST_ID (cr=2242 pr=0 pw=0 time=105774 us starts=1 cost=612 size=4999995 card=999999)(object id 191055)

 

8. 6번과 동일하지만 dynamic sampling 4 힌트를 주고 쿼리 수행

조건절을 여러 개 추가했을때 예상(E-rows)와 실제 결과(A-rows)의 차이가 있었습니다.

1,000,000건 중 6건 (0.0000006%)로 예상했지만 실제로는 1.540건의 결과값이 나왔습니다.

힌트가 먹히지 않은 것 같습니다.

select /*+ gather_plan_statistics dynamic_sampling(t1 4) */ 
count(*)
from ds_test t1, ds_test t2
   where t1.id = t2.id
   and t1.val in (select val from ds_test where val like '%Z')
   and  t1.val like '%O%' and t1.val like '%A%' and t1.val like '%G%';


SQL_ID  8th3gctd5p3qp, child number 0
-------------------------------------
select /*+ gather_plan_statistics dynamic_sampling(t1 4) */  count(*) 
from ds_test t1, ds_test t2    where t1.id = t2.id    and t1.val in 
(select val from ds_test where val like '%Z')    and  t1.val like '%O%' 
and t1.val like '%A%' and t1.val like '%G%'
 
Plan hash value: 2553999775
 
------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                |      1 |        |      1 |00:00:00.63 |   13620 |       |       |          |
|   1 |  SORT AGGREGATE        |                |      1 |      1 |      1 |00:00:00.63 |   13620 |       |       |          |
|*  2 |   HASH JOIN            |                |      1 |      1 |   1504 |00:00:00.62 |   13620 |  2401K|  2401K| 1350K (0)|
|*  3 |    HASH JOIN RIGHT SEMI|                |      1 |      1 |   1504 |00:00:00.42 |   11378 |  1209K|  1209K| 1659K (0)|
|*  4 |     TABLE ACCESS FULL  | DS_TEST        |      1 |      6 |   1504 |00:00:00.11 |    5689 |       |       |          |
|*  5 |     TABLE ACCESS FULL  | DS_TEST        |      1 |   1334 |   1504 |00:00:00.29 |    5689 |       |       |          |
|   6 |    INDEX FAST FULL SCAN| IDX_DS_TEST_ID |      1 |      1 |    999K|00:00:00.10 |    2242 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("T1"."ID"="T2"."ID")
   3 - access("T1"."VAL"="VAL")
   4 - filter(("VAL" LIKE '%Z' AND "VAL" LIKE '%O%' AND "VAL" LIKE '%A%' AND "VAL" LIKE '%G%' AND "VAL" IS NOT NULL 
              AND "VAL" IS NOT NULL AND "VAL" IS NOT NULL AND "VAL" IS NOT NULL))
   5 - filter(("T1"."VAL" LIKE '%O%' AND "T1"."VAL" LIKE '%A%' AND "T1"."VAL" LIKE '%G%' AND "T1"."VAL" LIKE '%Z' AND 
              "T1"."VAL" IS NOT NULL AND "T1"."VAL" IS NOT NULL AND "T1"."VAL" IS NOT NULL AND "T1"."VAL" IS NOT NULL))
 
Note
-----
   - dynamic statistics used: dynamic sampling (level=0)
   - this is an adaptive plan

====================================================================================================================================
tkprof

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          3          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.40       0.62          0      13620          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.40       0.63          0      13623          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 156
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=13620 pr=0 pw=0 time=627391 us starts=1)
      1504       1504       1504   HASH JOIN  (cr=13620 pr=0 pw=0 time=606631 us starts=1 cost=3169 size=72 card=1)
      1504       1504       1504    NESTED LOOPS  (cr=11378 pr=0 pw=0 time=322834 us starts=1 cost=3169 size=72 card=1)
      1504       1504       1504     STATISTICS COLLECTOR  (cr=11378 pr=0 pw=0 time=322582 us starts=1)
      1504       1504       1504      HASH JOIN RIGHT SEMI (cr=11378 pr=0 pw=0 time=421616 us starts=1 cost=3167 size=67 card=1)
      1504       1504       1504       TABLE ACCESS FULL DS_TEST (cr=5689 pr=0 pw=0 time=105180 us starts=1 cost=1583 size=186 card=6)
      1504       1504       1504       TABLE ACCESS FULL DS_TEST (cr=5689 pr=0 pw=0 time=296926 us starts=1 cost=1583 size=48024 card=1334)
         0          0          0     INDEX RANGE SCAN IDX_DS_TEST_ID (cr=0 pr=0 pw=0 time=0 us starts=0 cost=2 size=5 card=1)(object id 191055)
    999999     999999     999999    INDEX FAST FULL SCAN IDX_DS_TEST_ID (cr=2242 pr=0 pw=0 time=99243 us starts=1 cost=2 size=5 card=1)(object id 191055)

 

쿼리를 parsing할 때마다 dynamic sampling이 동작하여 통계정보를 일정부분 계속 수집한다면 성능은 자연스럽게 안좋아질것입니다.

테스트는 좀더 명확하게 dynamic sampling의 사용법과 효과에 대해서 잘 드러나지는 않는거 같네요..!

 

추가적으로 테스트하여 더욱 정확한 정보를 얻는다면 추가하겠습니다.

 

출처 : http://www.axiominfo.co.kr/default/article/column.php?com_board_basic=read_form&com_board_idx=74&&com_board_search_code=&com_board_search_value1=&com_board_search_value2=&com_board_page=9&&com_board_id=2&&com_board_id=2 

 

엑시엄에 오신것을 환영합니다

근래 오라클 9i 버전의 개발 지원 중단으로 인해 10g 또는 11g로 업그레이드를 진행하는 사이트가 늘어났다. 9i 버전의 오라클 Optimizer Mode 디폴트 값은 'CHOOSE'로 통계정보가 생성되어 있다면 CBO(Cost

www.axiominfo.co.kr

 

 

반응형

댓글