Optimizing Oracle Optimizer (2009년)
Correlated Columns 0 0 25,464

by 구루비스터디 cardinality Correlated Columns [2023.09.25]


  1. II. Correlated Columns
    1. II.1. 테스트 데이터 생성
    2. II.2. 통계정보 확인
    3. II.3. 테스트


II. Correlated Columns

II.1. 테스트 데이터 생성


-- create object
DROP TABLE T1 PURGE;

CREATE TABLE T1(C1 VARCHAR2(1), C2 INT);

-- create data
INSERT INTO T1
SELECT 'A', 1
FROM   DUAL
CONNECT BY LEVEL <= 1000
UNION ALL
SELECT 'B', 2
FROM   DUAL
CONNECT BY LEVEL <= 100
UNION ALL
SELECT 'C', 2
FROM   DUAL
CONNECT BY LEVEL <= 100
;

COMMIT;

-- gather stats "with" histogram
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T1', METHOD_OPT => 'FOR ALL COLUMNS SIZE SKEWONLY', NO_INVALIDATE => FALSE);


II.2. 통계정보 확인


-- Table
SELECT TABLE_NAME,
       NUM_ROWS,
       BLOCKS,
       SAMPLE_SIZE,
       TO_CHAR(LAST_ANALYZED, 'YYYY/MM/DD HH24:MI:SS') AS LAST_ANAL
FROM   USER_TAB_STATISTICS
WHERE  TABLE_NAME = UPPER('T1')
;


TABLE_NAMENUM_ROWSBLOCKSSAMPLE_SIZELAST_ANAL
T112001312002009-03-01 2:39:21 PM



-- Column
SELECT S.TABLE_NAME,
       S.COLUMN_NAME,
       S.NUM_DISTINCT,
       S.NUM_NULLS,
       S.DENSITY,
       S.LOW_VALUE,
       S.HIGH_VALUE,
       S.HISTOGRAM
FROM   USER_TAB_COLS S
WHERE  S.TABLE_NAME = UPPER('T1')
;


TABLE_NAMECOLUMN_NAMENUM_DISTINCTNUM_NULLSDENSITYLOW_VALUEHIGH_VALUEHISTOGRAM
T1C2200.000416666666666667C102C103FREQUENCY
T1C1300.0004166666666666674143FREQUENCY



-- Histogram
SELECT TABLE_NAME,
       COLUMN_NAME,
       ENDPOINT_NUMBER,
       ENDPOINT_VALUE || '(' || ENDPOINT_ACTUAL_VALUE || ')' AS ENDPOINT_VALUE
FROM   USER_TAB_HISTOGRAMS
WHERE  TABLE_NAME = UPPER('T1')
ORDER  BY COLUMN_NAME,
          ENDPOINT_NUMBER
;


TABLE_NAMECOLUMN_NAMEENDPOINT_NUMBERENDPOINT_VALUE
T1C11000337499295804764000000000000000000000()
T1C11100342691592663299000000000000000000000()
T1C11200347883889521833000000000000000000000()
T1C210001()
T1C212002()


II.3. 테스트

1) C1 Columns 'A' Cardanality with histogram

SELECT /*+ GATHER_PLAN_STATISTICS */
       COUNT(*)
FROM   T1
WHERE  C1 = 'A'
;

select * from table(dbms_xplan.display_cursor(null, null, 'iostats cost last'));

--------------------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------
|   1 |  SORT AGGREGATE    |      |      1 |      1 |            |      1 |00:00:00.01 |      15 |
|*  2 |   TABLE ACCESS FULL| T1   |      1 |   1000 |     5   (0)|   1000 |00:00:00.01 |      15 |
--------------------------------------------------------------------------------------------------
;


2) C1 = 'A' AND C2 = 1
  • = Base Cardinality * Selectivity
  • = Base Cardinality * Selectivity(C1 = 'A' AND C2 = 1)
  • = Base Cardinality * Selectivity(C1 = 'A') * Selectivity(C2 = 1)
  • = 1200 * 1000/1200 * 1000/1200
  • = 833



SELECT /*+ GATHER_PLAN_STATISTICS */
       COUNT(*)
FROM   T1
WHERE  C1 = 'A'
AND    C2 = 1
;

select * from table(dbms_xplan.display_cursor(null, null, 'iostats cost last'));

--------------------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------
|   1 |  SORT AGGREGATE    |      |      1 |      1 |            |      1 |00:00:00.01 |      15 |
|*  2 |   TABLE ACCESS FULL| T1   |      1 |    833 |     5   (0)|   1000 |00:00:00.01 |      15 |
--------------------------------------------------------------------------------------------------
;


3) C1 = 'A' AND C2 = 2
  • = Base Cardinality * Selectivity
  • = Base Cardinality * Selectivity(C1 = 'A' AND C2 = 2)
  • = Base Cardinality * Selectivity(C1 = 'A') * Selectivity(C2 = 2)
  • = 1200 * 1000/1200 * 200/1200
  • = 166



SELECT /*+ GATHER_PLAN_STATISTICS */
       COUNT(*)
FROM   T1
WHERE  C1 = 'A'
AND    C2 = 2
;

select * from table(dbms_xplan.display_cursor(null, null, 'iostats cost last'));

--------------------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------
|   1 |  SORT AGGREGATE    |      |      1 |      1 |            |      1 |00:00:00.01 |      15 |
|*  2 |   TABLE ACCESS FULL| T1   |      1 |    166 |     5   (0)|      0 |00:00:00.01 |      15 |
--------------------------------------------------------------------------------------------------
;


4. Exetended Statistics
  • 10g까지는 Column들간으 상호 의존성을 Oracle이 인식하도록 할 수 있는 방법은 없다
  • 11g부터는 Extended Statistics를 이용해 Column들간의 상호 의존성을 통계 정보에 저장 가능


  • 구문

 EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T1', METHOD_OPT => 'FOR COLUMNS (C1, C2) SIZE SKEWONLY', NO_INVALIDATE => FALSE);

"데이터베이스 스터디모임" 에서 2009년에 "OPTIMIZING ORACLE OPTIMIZER " 도서를 스터디하면서 정리한 내용 입니다.

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

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

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

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