Optimizing Oracle Optimizer (2011년)
Frequency Histogram 0 0 2,345

by 구루비스터디 Histogram Cardinality [2018.07.14]


Frequency Histogram

  • 장점 : 특정 값(Value)에 해당하는 빈도(Frequency)를 정확하게 알 수 있다. 단 Literal 일 경우.


Bind 변수를 사용 시
Predicaete TypeCardinality
Predicate ( = )1/NDV11111 * 1/5 = 22222
Range Predicate ( >, <, etc)5% rule11111 * 0.05 = 556
Between Predicate5% rule11111 * 0.05 * 0.05 = 27.77 = 28


  • 존재하지 않은 값에 대해서는 0으로 계산(10.2.0.4버전부터는 Bucket의 최소빈도/2의 값을 사용)
  • Histogram에 존재하지 않은 값에 대한 Cardinality의 계산 방법 => Manual하게 Histogram생성(7장)


예제


TABLE_NAME                    : T1
COLUMN_NAME                   : C1
NUM_DISTINCT                  : 5
NUM_NULLS                     : 0
DENSITY                       : .0000450004500045
LOW_VALUE                     : C102
HIGH_VALUE                    : C106
HISTOGRAM                     : FREQUENCY



컬럼 C1에 대한 Histogram 정보 - Frequency Histogram

        C1        CNT
---------- ----------
         1      10000
         2       1000
         3        100
         4         10
         5          1



TABLE_NAME           COLUMN_NAME          ENDPOINT_NUMBER ENDPOINT_VALUE
-------------------- -------------------- --------------- --------------------
T1                   C1                             10000 1()
T1                   C1                             11000 2()
T1                   C1                             11100 3()
T1                   C1                             11110 4()
T1                   C1                             11111 5()


Literal 의 경우

SQL> explain plan for
  2  select * from t1 where c1 = 1;
  
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 | 60000 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   | 10000 | 60000 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("C1"=1)

  • Cardinality : 10000 으로 예측


Literal(c1=2)

SQL> explain plan for
  2  select * from t1
  3  where c1 = 2;

해석되었습니다.

SQL> @plan

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  1000 |  6000 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |  1000 |  6000 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("C1"=2)

  • Cardinality : 1000 으로 예측


Bind 변수 : Predicate (c1=:b1)

SQL> explain plan for
  2  select * from t1
  3  where c1 = :b1;

해석되었습니다.

SQL> @plan

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  2222 | 13332 |     7  (15)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |  2222 | 13332 |     7  (15)| 00:00:01 |
--------------------------------------------------------------------------

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("C1"=TO_NUMBER(:B1))

  • Cardinality : 1/NDV = (11111*1/5 = 2222)


Bind 변수 : Range Predicate (c1>:b1)

SQL> explain plan for
  2  select * from t1
  3  where c1 > :b1;

해석되었습니다.

SQL> @plan

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  2223 | 13338 |     7  (15)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |  2223 | 13338 |     7  (15)| 00:00:01 |
--------------------------------------------------------------------------

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("C1">TO_NUMBER(:B1))

  • Cardinality : 5% rule 적용(11111*0.05=556) 이어야 하는데... 결과는 다르다. 근거를 알 수가 없음...


Bind변수 : Between Predicate(c1 between :b1 and :b2)

SQL> explain plan for
  2  select * from t1
  3  where c1 between :b1 and :b2;

해석되었습니다.

SQL> @plan

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3332582666

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |   445 |  2670 |     7  (15)| 00:00:01 |
|*  1 |  FILTER            |      |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| T1   |   445 |  2670 |     7  (15)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   1 - filter(TO_NUMBER(:B1)<=TO_NUMBER(:B2))
   2 - filter("C1">=TO_NUMBER(:B1) AND "C1"<=TO_NUMBER(:B2))

  • Cardinality : 5% rule 적용(11111*0.05*0.05=28) 이어야 하는데... 또 결과는 다르다. 뭘까...


존재하지 않는 값 (c1=-1)

SQL> explain plan for
  2  select * from t1
  3  where c1 = -1;

해석되었습니다.

SQL> @plan

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     6 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |     1 |     6 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("C1"=(-1))

  • Cardinality : 1 (Oracle 10.2.0.4부터는 1이 아닌 Bucket의 최소빈도/2를 사용)
"데이터베이스 스터디모임" 에서 2009년에 "OPTIMIZING ORACLE OPTIMIZER " 도서를 스터디하면서 정리한 내용 입니다.

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

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

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

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