Optimizing Oracle Optimizer (2011년)
Cardinality Matters 0 0 2,476

by 구루비스터디 Cardinility [2018.07.14]


목차

  1. 목차
  2. I. Cardinality Matters
  3. II. Cardinality 기본 개념
  4. III. Basic Rules


I. Cardinality Matters

  • Cardinality = 집합안의 원소 갯수, Oracle예상 row수
  • 1. The most common reason for poor execution plans with perceived "good" statistics is inaccurate row count estimates.
  • "좋은" 통계 정보를 가지고도 실행 계획이 비효율적으로 수립되는 가장 흔한 이유는 예측 Row 수가 부정확하기 때문이다.
  • Oracle Engineer - Andrew Holdsworth


  • 2. If an access plan is not optimal it is because the cardinality estimate for ont or more of the row sources is grossly incorrect
  • 만일 실행 계획이 불량하다면 Row Source(실행 계획의 각 단계)들 중 하나 이상에서 예측 Row 수가 매우 부정확하기 때문이다.
  • Technical Reviewer - Wolfgang Breitling


  • Optimizer가 실행계획을 세우는데 있어 가장 중요한 것은 정확한 Cardinality의 계산이며 동시에 그것은 실행계획이 비효율적인 가장 큰 원인이 된다.


II. Cardinality 기본 개념

  • 1. Cardinality of a set is the number of elements of the set Cardinality는 특정 집합에 속한 원소(element)의 수를 의미한다.
  • 2. Oracle에서는 Cardinality 의미를 다음의 4가지로 사용


Base Cardinality
  • Base Cardinality란 특정 Table의 전체 Row 수를 의미한다.
  • dba_tables.num_rows 값이라고 볼 수 있다.


Calculated Cardinality
  • Calculated Cardinality란 Predicate, 즉 조건 절에 의해 Filtering된 Row수를 의미한다.
  • 가령 Table t1의 전체 Row수가 1000건이고 t1.c1 > 100 조건을 만족하는 Row 수가 100건이라고 가정한다면
  • 이 경우 Base Cardinality(t1) = 1000이 되고, Calculated Cardinality(t1.c1 > 100) = 100이 된다.


Estimated Cardinality
  • Base Cardinality 또는 Calculated Cardinality 모두 Oracle이 실행계획을 세우는 단계에서 사용하는 모든 Cardinality는 예측치이며 이것을 Estimated Cardinality라고 부른다.


Actual Cardinality
  • Query를 수행한 후 계산된 실제 Row 수를 의미함.
  • Estimated Cardinality가 실행계획을 수립하는 단계에서 계산되는 반면 Actual Cardinality는 실제 수행한 후에만 알 수 있다.
  • Estimated Cardinality 값과 Actual Cardinality 값이 큰 차이를 보인다면 Oracle의 예측이 부정확했다는 것을 의미


3. 이 책에서는 Calculated Cardinality + Estimated Cardinality


III. Basic Rules



SQL> explain plan for
  2  select count(*)
  3  from t1
  4  where c1 between 1 and 10
  5  ;
                                     
                                                                                
---------------------------------------------------------------------------     
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |     
---------------------------------------------------------------------------     
|   0 | SELECT STATEMENT   |      |     1 |     4 |    14   (0)| 00:00:01 |     
|   1 |  SORT AGGREGATE    |      |     1 |     4 |            |          |     
|*  2 |   TABLE ACCESS FULL| T1   |    10 |    40 |    14   (0)| 00:00:01 |     
---------------------------------------------------------------------------     



  • explain plan에서의 Rows는 Estimated Cardinality를 의미한다.
  • 현재 10건 정도의 row가 추출될 것으로 추측


SQL> select /*+ gather_plan_statistics */
  2    count(*)
  3  from t1
  4  where c1 between 1 and 10
  5  ;

  COUNT(*)                                                                      
----------                                                                      
        10  

--------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | Cost (%CPU)| A-Rows |     
                                                                                
--------------------------------------------------------------------------------            
|   1 |  SORT AGGREGATE    |      |      1 |      1 |            |      1 |                                                          
|*  2 |   TABLE ACCESS FULL| T1   |      1 |     10 |    14   (0)|     10 |
--------------------------------------------------------------------------------  



  • A-row와 E-row가 정확히 일치함을 볼수 있다. 그러나 항상 일치하는 것은 아니다. 대부분의 경우에 E-row는 부정확하다.




SQL> explain plan for
  2  select count(*)
  3  from t1
  4  where c2 = 1
  5  ;                                                  
                                                                                
---------------------------------------------------------------------------     
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |     
---------------------------------------------------------------------------     
|   0 | SELECT STATEMENT   |      |     1 |     3 |    14   (0)| 00:00:01 |     
|   1 |  SORT AGGREGATE    |      |     1 |     3 |            |          |     
|*  2 |   TABLE ACCESS FULL| T1   |  1000 |  3000 |    14   (0)| 00:00:01 |     
---------------------------------------------------------------------------     

-------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | Cost (%CPU)| A-Rows |       
--------------------------------------------------------------------------------
|   1 |  SORT AGGREGATE    |      |      1 |      1 |            |      1 |
|*  2 |   TABLE ACCESS FULL| T1   |      1 |   1000 |    14   (0)|    960 |  
--------------------------------------------------------------------------------


  • 위의 경우에는 A-row와 E-row가 불일치 함을 볼수 있다.


Density 와 Selectivity
  • 데이터 생성 결과

TABLE_NAME                    : T1
COLUMN_NAME                   : C1
NUM_DISTINCT                  : 10000
NUM_NULLS                     : 0
DENSITY                       : .0001
LOW_VALUE                     : C102
HIGH_VALUE                    : C302
HISTOGRAM                     : NONE
-----------------
TABLE_NAME                    : T1
COLUMN_NAME                   : C2
NUM_DISTINCT                  : 10
NUM_NULLS                     : 0
DENSITY                       : .1
LOW_VALUE                     : 80
HIGH_VALUE                    : C10A
HISTOGRAM                     : NONE
-----------------
TABLE_NAME                    : T1
COLUMN_NAME                   : C3
NUM_DISTINCT                  : 100
NUM_NULLS                     : 0
DENSITY                       : .01
LOW_VALUE                     : 786B0B17010101
HIGH_VALUE                    : 786C0301010101
HISTOGRAM                     : NONE
-----------------
TABLE_NAME                    : T1
COLUMN_NAME                   : C4
NUM_DISTINCT                  : 100
NUM_NULLS                     : 0
DENSITY                       : .01
LOW_VALUE                     : 3230303731313233
HIGH_VALUE                    : 3230303830333031
HISTOGRAM                     : NONE



h6 Density

  • Density란 column의 농도, 컬럼값의 밀도(1 / NDV)로 나타낼수 있다.


Distinct Count
  • Number of Distinct Values, Distinct count가 작을수록 column의 농도는 진하다.


Skewness
  • Data가 특정 값에 몰려있을 경우 Dkewness가 높다고 한다.
  • Historgram으로 표현하며, Historgram이 존재하는 경우 Skewness를 반영하기 위해 별도의 Density를 계산한다


Selectivity
  • 특정 조건의 선택도를 의미한다.
  • Density는 특정 컬럼(하나)의 고정된 값인 반면 Selectivity는 동적 컬럼의 값
  • Estimated Cardinality 값과 Actual Cardinality 값이 큰 차이를 보인다면 Oracle의 예측이 부정확했다는 것을 의미


  • Selectivity는 Predicate에 따라 변하는 속성이다.


1. c1 컬럼에 literal

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

  • Cardinality = 10000 * Selectivity = 10000 * 0.0001 = 1


2. c2 컬럼에 literal

SQL> explain plan for
  2  select *
  3  from t1
  4  where c2 = 1
  5  ;
         
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |  1000 | 23000 |    14   (0)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |  1000 | 23000 |    14   (0)| 00:00:01 |      
--------------------------------------------------------------------------     

  • Cardinality = 10000 * Selectivity = 10000 * 0.1 = 1000


3. c1 컬럼에 Bind 변수

SQL> explain plan for
  2  select *
  3  from t1
  4  where c1 = :b1
  5  ;
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |     1 |    23 |    15   (7)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |     1 |    23 |    15   (7)| 00:00:01 |      
--------------------------------------------------------------------------    

  • Cardinality = 10000 * Selectivity = 10000 * 0.0001 = 1



SQL> explain plan for
  2  select *
  3  from t1
  4  where c2 = :b1
  5  ;
                                             
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |  1000 | 23000 |    15   (7)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |  1000 | 23000 |    15   (7)| 00:00:01 |      
--------------------------------------------------------------------------  

  • Cardinality = 10000 * Selectivity = 10000 * 0.1 = 1000
  • HISTOGRAM 이 없으므로 literal과 차이가 없다.


3. Between 연산

SQL> explain plan for
  2  select *
  3  from t1
  4  where c1 between 1 and 100
  5  ;
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   100 |  2300 |    14   (0)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   100 |  2300 |    14   (0)| 00:00:01 |      
-------------------------------------------------------------------------- 


 
*Cardinality* 	= Base Cardinality * (Selectivity(C1 BETWEEN X AND Y))
   	= Base Cardinality * (Selectivity(C1 = X) + Selectivity(C1 = Y) + Selectivity(X < C1 < Y))
   	= Base Cardinality * (Selectivity(C1 = X) + Selectivity(C1 = Y) + (Y - X)/(MAX - MIN))
   	= Base Cardinality * (Selectivity(C1 = 1) + Selectivity(C1 = 100) + (100 - 1)/(10000 - 1))
   	= 10000 * (0.0001 + 0.0001 + (99)/(9999))
   	= 10000 * (0.0001 + 0.0001 + 0.00990099)
   	= 10000 * 0.01000099
   	= 100


3. 2개 이상의 Predicate

SQL> explain plan for
  2  select *
  3  from t1
  4  where c1 between 1 and 100 and
  5        c2 = 1
  6  ;
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |    10 |   230 |    14   (0)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |    10 |   230 |    14   (0)| 00:00:01 |      
--------------------------------------------------------------------------  


   
*Cardinality* 	= Base Cardinality * (Selectivity(C1 BETWEEN X AND Y)) * (SELECTIVITY(C2 = 1))
		= 10000 * 0.01 * 0.1
		= 0.001



SQL> explain plan for
  2  select *
  3  from t1
  4  where c1 between 1 and 100 or
  5        c2 = 1
  6  ;

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



*Cardinality* 	= Base Cardinality * (Selectivity(P1 OR P2))
		= Base Cardinality * (Selectivity(P1) + Selectivity(P2) - Selectivity(P1 AND P2))
		= Base Cardinality * (Selectivity(P1) + Selectivity(P2) - (Selectivity(P1) * Selectivity(P2)))
		= 10000 * (0.01 + 0.1 - (0.01 * 0.1))
		= 10000 * (0.109) = 1090


h6 3. date Type


SQL> explain plan for
  2  select *
  3  from t1
  4  where c3 = to_date('20080201','yyyymmdd')
  5  ;
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   100 |  2300 |    14   (0)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   100 |  2300 |    14   (0)| 00:00:01 |      
--------------------------------------------------------------------------      

  • Cardinality = Base Cardinality * Selectivity = 10000 * 0.01 = 100



SQL> explain plan for
  2  select *
  3  from t1
  4  where c4 = '20080201'
  5  ;                                            
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   100 |  2300 |    14   (0)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   100 |  2300 |    14   (0)| 00:00:01 |      
--------------------------------------------------------------------------     

  • Cardinality = Base Cardinality * Selectivity = 10000 * 0.01 = 100



SQL> explain plan for
  2  select *
  3  from t1
  4  where c3 between to_date('20071231','yyyymmdd')
  5        and to_date('20080110','yyyymmdd')
  6  ;
                                                                   
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |  1210 | 27830 |    14   (0)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |  1210 | 27830 |    14   (0)| 00:00:01 |      
--------------------------------------------------------------------------    



*Cardinality* 	= Base Cardinality * (Selectivity(C3 BETWEEN P1 AND P2))
		= Base Cardinality * (Selectivity(P1) + Selectivity(P2) + Selectivity(P1 < C1 < P2))
		= Base Cardinality * (Selectivity(P1) + Selectivity(P2) + (P2 - P1)/(MAX - MIN))
		= 10000 * (0.01 + 0.01 + (2008/01/10 - 2007/12/31) / (2008/03/01 - 2007/11/23))
		= 10000 * (0.01 + 0.01 + (10)/(99))
		= 10000 * 0.121010101
		= 1210



SQL> explain plan for
  2  select *
  3  from t1
  4  where c4 between '20071231'
  5        and '20080110'
  6  ;                    
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |  9874 |   221K|    15   (7)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |  9874 |   221K|    15   (7)| 00:00:01 |      
--------------------------------------------------------------------------   



*Cardinality* 	= Base Cardinality * (Selectivity(C4 BETWEEN P1 AND P2))
		= Base Cardinality * (Selectivity(P1) + Selectivity(P2) + Selectivity(P1 < C4 < P2))
		= Base Cardinality * (Selectivity(P1) + Selectivity(P2) + (P2 - P1)/(MAX - MIN))
		= 10000 * (0.01 + 0.01 + (20080110 - 20071231) / (20080301 - 20071123))
		= 10000 * (0.01 + 0.01 + (8879) / (9178))
		= 10000 * 0.987422096
		= 9874

Magic Numbers
  • Selectivity를 계산할 수 없는 경우에 대한 test


1. Bind 변수와 Range Predicate가 함께 사용된 경우

SQL> explain plan for
  2  select *
  3  from t1
  4  where c1 > :b1
  5  ;
        
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   500 | 11500 |    15   (7)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   500 | 11500 |    15   (7)| 00:00:01 |      
--------------------------------------------------------------------------      

  • Rows = 500 즉, Cardinality는 500 이다.
  • 이것은 5%의 magic number를 사용한 것을 의미한다
  • Cardinality = 10000 * 5% = 10000 * 0.05 = 500
  • Bind 변수와 Range Predicate가 함께 사용된 경우 Selectivity 계산이 안되기 때문에 5%의 Rule이 사용된다.
    (컬럼 c1이나 c2 둘다 마찬가지임을 확인)



SQL> explain plan for
  2  select *
  3  from t1
  4  where c1 >= :b1
  5  ;
                                 
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   500 | 11500 |    15   (7)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   500 | 11500 |    15   (7)| 00:00:01 |      
--------------------------------------------------------------------------      
                                                                                

SQL> explain plan for
  2  select *
  3  from t1
  4  where c2 > :b1
  5  ;

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


2. Bind 변수와 Between Predicate가 함께 사용된 경우
  • 다음 c1 between :b1 and :b2 의 조건이 |c1 >= :b1| and |c2 <= :b2| 로 치환된다

Selectivity = 5%* 5% = 0.25%가 된다.
Cardinality = 10000 * 25% = 10000 * 0.0025 = 25


SQL> explain plan for
  2  select *
  3  from t1
  4  where c1 between :b1 and :b2
  5  ;
                                  
---------------------------------------------------------------------------     
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |     
---------------------------------------------------------------------------     
|   0 | SELECT STATEMENT   |      |    25 |   575 |    15   (7)| 00:00:01 |     
|*  1 |  FILTER            |      |       |       |            |          |     
|*  2 |   TABLE ACCESS FULL| T1   |    25 |   575 |    15   (7)| 00:00:01 |     
---------------------------------------------------------------------------     



3. Function Predicate가 사용된 경우의 magic Number

SQL> create or replace function f1(v1 int)
  2    return int
  3  is
  4  begin
  5    return v1;
  6  end f1;
  7  /

함수가 생성되었습니다.


SQL> explain plan for
  2  select *
  3  from t1
  4  where f1(c1) = 1
  5  ;
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   100 |  2300 |    19  (27)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   100 |  2300 |    19  (27)| 00:00:01 |      
--------------------------------------------------------------------------      

  • Function Predicate의 Magic Number는 1% 이다.
  • 위의 결과 역시 1%의 selectivity를 사용하여 나온 값과 일치한다.

Cardinality = 10000 * 1% = 10000 * 0.01 = 100

  • 다른 경우들도 같음을 확인할 수 있다.



SQL> explain plan for
  2  select *
  3  from t1
  4  where f1(c2) = 1
  5  ;                                        
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   100 |  2300 |    19  (27)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   100 |  2300 |    19  (27)| 00:00:01 |      
--------------------------------------------------------------------------      


4. Function Predicate가 Range 연산과 함께 사용된 경우는 다시 5%의 Rule 이 적용됩니다.

SQL> explain plan for
  2  select *
  3  from t1
  4  where f1(c1) > 1
  5  ;
                                          
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   500 | 11500 |    19  (27)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   500 | 11500 |    19  (27)| 00:00:01 |      
--------------------------------------------------------------------------      

  • Cardinality = 10000 * 5% = 10000 * 0.05 = 500


                                           
SQL> explain plan for
  2  select *
  3  from t1
  4  where f1(c1) between 1 and 100
  5  ;
                                              
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |    25 |   575 |    20  (30)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |    25 |   575 |    20  (30)| 00:00:01 |      
--------------------------------------------------------------------------      

  • Cardinality = 10000 * 25% = 10000 * 0.0025 = 25


5. Function Predicate가 Range 연산, Bind 변수가 함께 사용된 경우도 5%의 Rule 이 적용됩니다.

SQL> explain plan for
  2  select *
  3  from t1
  4  where f1(c1) between :b1 and :b2
  5  ;
    
---------------------------------------------------------------------------     
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |     
---------------------------------------------------------------------------     
|   0 | SELECT STATEMENT   |      |    25 |   575 |    20  (30)| 00:00:01 |     
|*  1 |  FILTER            |      |       |       |            |          |     
|*  2 |   TABLE ACCESS FULL| T1   |    25 |   575 |    20  (30)| 00:00:01 |     
---------------------------------------------------------------------------     

  • Cardinality = 10000 * 25% = 10000 * 0.0025 = 25


  • function연산에서의 cardinality는 부정확할 수밖에 없다. 실제 데이터 분포와 상관없이 1% or 5% magic number를 사용하기 때문이다.
  • 이것의 해결법은 Function Based Index 를 사용하는 것이다.


6. Function Predicate에 사용되는 Magic Number는 Function에 의한 변형이 발생한 경우에만 해당한다
  • 단순히 값을 제공하는 경우에는 Magic Number가 아닌 density가 사용 된다.

SQL> explain plan for
  2  select *
  3  from t1
  4  where c1 = f1(c1)
  5  ;

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

  • c1의 density(c1) = 1/10000 = 0.0001 이다
  • Cardinality = 10000 * 1% = 10000 * 0.0001 = 1


7. Like Predicate가 사용되는 예 - 단순 상수와 사용된 예

SQL> explain plan for
  2  select *
  3  from t1
  4  where c4 like '20080101'
  5  ;
                                              
                                                                                
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   100 |  2300 |    14   (0)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   100 |  2300 |    14   (0)| 00:00:01 |      
--------------------------------------------------------------------------      

  • Cardinality = 10000 * 1% = 10000 * 0.01 = 100


7. Like Predicate가 사용되는 예 - Bind변수와 함께 사용된 예

SQL> explain plan for
  2  select *
  3  from t1
  4  where c4 like :b1
  5  ;

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

  • Cardinality = 10000 * 5% = 10000 * 0.05 = 500


7-3. Parameter 제어
  • _like_with_bind_as_equality Parameter 는 기본적으로 사용되는 magic number 5% 대신에 Equality Predicate와 동일하게 처리한다.

SQL> explain plan for
  2  select /*+ opt_param('_like_with_bind_as_equality', 'true') */
  3    *
  4  from t1
  5  where c4 like :b1
  6  ;
                                    
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |     
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   101 |  2323 |    15   (7)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   101 |  2323 |    15   (7)| 00:00:01 |      
--------------------------------------------------------------------------      


7-4. '%' 앞에 등장하는 경우 5% Rule

SQL> explain plan for
  2  select *
  3  from t1
  4  where c4 like '%2008'
  5  ;
                   
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   500 | 11500 |    15   (7)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   500 | 11500 |    15   (7)| 00:00:01 |      
--------------------------------------------------------------------------      

  • Cardinality = 10000 * 5% = 10000 * 0.05 = 500


7-5. '%' 앞뒤로 등장하는 경우 5% Rule

SQL> explain plan for
  2  select *
  3  from t1
  4  where c4 like '%2008%'
  5  ;
   
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |   500 | 11500 |    15   (7)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| T1   |   500 | 11500 |    15   (7)| 00:00:01 |      
--------------------------------------------------------------------------      

  • Cardinality = 10000 * 5% = 10000 * 0.05 = 500
  • Like Predicate는 "%"의 위치에 따라 매우 다양한 cardinality 값을 보여준다
"데이터베이스 스터디모임" 에서 2009년에 "OPTIMIZING ORACLE OPTIMIZER " 도서를 스터디하면서 정리한 내용 입니다.

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

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

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

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