ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SQL BOOSTER - 단일 인덱스
    DataBase/SQL 2024. 6. 12. 11:31

     

    단일 인덱스의 컬럼 정하기 

     

    인덱스는 조건에 맞는 데이터를 빠르게 찾기 위한 객체이다. 

    WHERE 조건절에 사용된 컬럼에 인덱스를 구성하는 것이 기본 원리다. 

     

    SELECT /*+ GATHER_PLAN_STATISTICS*/
    TO_CHAR(T1.ORD_DT,'YYYYMM'), COUNT(*)
    FROM T_ORD_BIG T1
    WHERE T1.CUS_ID = 'CUS_0064'
    AND T1.PAY_TP = 'BANK'
    AND T1.RNO = 2
    GROUP BY TO_CHAR(T1.ORD_DT,'YYYYMM');

     

    이제 성능 개선을 위해 단 하나의 단일 인덱스를 고려해보자 

    후버 컬럼은 WHERE 조건절에 사용된 CUS_ID, PAY_TP, RNO컬럼이다. 

    SELECT 'CUS_ID' COL, COUNT(*) CNT FROM T_ORD_BIG T1 WHERE T1.CUS_ID = 'CUS_0064'
    UNION ALL 
    SELECT 'PAY_TP' COL, COUNT(*) CNT FROM T_ORD_BIG T1 WHERE T1.PAY_TP = 'BANK'
    UNION ALL 
    SELECT 'RNO' COL, COUNT(*) CNT FROM T_ORD_BIG T1 WHERE T1.RNO = 2

    SQL BOOSTER

     

    인덱스 컬럼 선정의 규칙 중 하나는 선택성이 좋은 컬럼을 사용하는 것 

    주어진 조건에 데이터가 적을수록 선택성이 좋고, 조건에 해당하는 데이터가 많을수록 선택성이 나쁘다.

     

    RNO = 2 조건의 결과가 3047건으로 가장 적다. RNO 조건이 선택성이 가장 좋고, 그 다음 CUS_ID가 좋다.

    성능을 위한 인덱스를 하나 만들어야 한다면, RNO 컬럼에 만드는 것이 좋다. 

     

    CREATE INDEX X_T_ORD_BIG_2 ON T_ORD_BIG(RNO);
    
    SELECT /*+ GATHER_PLAN_STATISTICS INDEX (T1 X_T_ROD_BIG_2) */
    FROM T_ORD_BIG T1
    WHERE T1.CUS_ID = 'CUS_0064'
    AND T1.PAY_TP ='BANK'
    AND T1.RNO =2
    GROUP BY TO_CHAR(T1.ORD_DT ,'YYYYMM');

    SQL BOOSTER

     

    SQL을 결과에 대한 실행 계획으로 위에 테이블을 얻을 수 있다. 

     

    • X_T_ORD_BIG_2 인덱스를 이용해 조건에 맞는 데이터를 찾는다. -> 3047건
    • 찾아낸 3047건에 대해 TABLE ACCESS BY INDEX ROWID를 수행 -> 2건의 결과 
    • 마지막으로 GROUP BY를 수행 
    CREATE INDEX X_T_ORD_BIG_3 ON T_ORD_BIG(CUS_ID);

     

    인덱스를 변경하고 같은 SQL을 돌려보자 결과는 아래와 같다.

    SQL BOOSTER

    이전보다 오래 걸링 원인은 INDEX RANGE SCAN 단계의 A-Rows가 340K이므로, TABLE ACCESS BY INDEX ROWID가 340k번 수행된다. 

    SQL BOOSTER

    RNO가 2인 데이터는 3047건이므로 TABLE ACCESS BY INDEX ROWID도 3047번이다. 하지만, CUS_ID는 340000건이므로 테이블 엑세스도 340000번 수행된다. 

     


    단일 인덱스 VS 복합 인덱스

     

    복합 인덱스는 단일 인덱스를 능가하는 성능을 낼 수 있다. 하나의 복합 인덱스로 여러 개의 인덱스를 대신 할 수 있는 장점도 있다.

    인덱스가 많아질수록 입력, 수정 삭제 성능 감소가 발생한다. 

    이와 같은 이유로 복합 인덱스를 이용해 인덱스의 수를 줄이는 것이 매우 중요하다. 

     

    DROP INDEX X_T_ORD_BIG_3; --인덱스 제거
    
    SELECT /*+ GATHER_PLAN_STATISTICS INDEX(T1 X_T_ORD_BIG_1) */
    T1.ORD_ST, COUNT(*)
    FROM T_ORD_BIG T1
    WHERE T1.ORD_YMD LIKE '201703%'
    AND T1.CUS_ID = 'CUS_0075'
    GROUP BY T1.ORD_ST;

    SQL BOOSTER

    행 계획을 보면,  실행시간은 6.61초, Bufferes는 338K, INDEX RANGE SCAN은 1850K이다

     

    이번에는 WHERE 조건절에 사용된 ORD_YMD와 CUS_ID 컬럼 두 개를 모두 포함하는 복합 인덱스를 만들어보자 

    CREATE INDEX X_T_ORD_BIG_3 ON T_ORD_BIG(ORD_YMD,CUS_ID);
    SELECT /*+ GATHER_PLAN_STATISTICS INDEX(T1 X_T_ORD_BIG_3) */
    T1.ORD_ST, COUNT(*)
    FROM T_ORD_BIG T1
    WHERE T1.ORD_YMD LIKE '201703%'
    AND T1.CUS_ID = 'CUS_0075'
    GROUP BY T1.ORD_ST;

    SQL BOOSTER

     

    실행계획을 확인하면, 전체 실행 시간이 1.49초로 개선되었다. 

    INDEX RANGE SCAN의 A-Rows가 30000에 불과하다. 

    SQL BOOSTER

     

    복합 인덱스를 사용한 리프 블록을 보면, ORDER BY 결과처럼 ORD_YMD별로 정렬된 후 CUS_ID로 데이터가 정력되어 있다.

     

    단일 인덱스의 경우 ORD_YMD 조건은 인덱스를 이용했지만, CUS_ID를 확인하기 위해서는 테이블에 방문해야만 알 수 있다. 

    'DataBase > SQL' 카테고리의 다른 글

    SQL BOOSTER - 인덱스로 커버된 SQL  (0) 2024.06.12
    SQL BOOSTER - 복합인덱스  (1) 2024.06.12
    성능 개선을 위한 기본 지식 - 실행 계획  (0) 2024.06.06
    SQLBOOSTER - RANGE JOIN  (1) 2024.06.06
    SQLBOOSTER - INNER JOIN  (0) 2024.06.04
Designed by Tistory.