ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SQL BOOSTER - SQL 작성 가이드 (2)
    DataBase/SQL 2024. 7. 15. 09:43

     

    1. 불필요한 COUNT는 하지 않는다.

     

    COUNT(*)는 데이터 건수를 세는 집계함수이다. 데이터 존재 여부를 확인하기 위해 COUNT(*)를 사용하는 경우가 많다.

    SELECT COUNT(*)
    FROM T_ORD_BIF T1
    WHERE T1.ORD_YMD = '20170225'
    AND T1.CUS_ID = 'CUS_0006';

    SQL BOOSTER

    실행계획을 보면 INDEX RANGE SCAN단계의 A-ROWS가 10,000건이다. 카운트 했기 때문에 주문을 모두 읽은 것이다.

    단발성 SQL이라면, 큰 부담이 없겠지만, 

    고객이 주문할 때마다 실행되는 SQL이라면, 최적화할 필요가 있다. 

     

    SELECT NVL(MAX(1),0)
    FROM DUAL A
    WHERE EXISTS(
    			SELECT * 
                FROM T_ORD_BIG T1
                WHERE T1.ORD_YMD = '20170225'
                AND T1.CUS_ID = 'CUS_0006'
    );

    SQL BOOSTER

    이와 같이 최적화 할 수 있다. INDEX RANGE SCAN A-Rows가 1이다. Bufferes 수치도 4밖에 되지 않는다.

     

    2. COUNT에 불필요한 부분은 제거한다. 

     

    SELECT T1.ORD_SEQ, T1.RNO, T1.ORD_YMD, T1.CUS_ID, T2.CUS_NM, T3.BAS_CD_NM ORD_ST_NM
    FROM T_ORD_BIG T1, M_CUS T2, C_BAS_CD T3
    WHERE T1.ORD_YMD = '20170107'
    AND T2.CUS_ID = T1.CUS_ID
    AND T3.LNG_CD = 'KO'
    AND T3.BAS_CD_DV = 'ORD_ST'
    AND T3.BAS_CD = T1.ORD_ST
    ORDER BY T1.ORD_SEQ, T1.RNO;

     

    주문정보와 함께 고객이름을 보여주기 위해 고객 테이블과 조인하고 있다. 지금은 크게 문제될 것이 없다.

    다만, 위 SQL의 전체 건수를 보여주기 위해 아래와 같은 패턴으로 개발할 수도 있다. 

     

    SELECT COUNT(*)
    FROM (
    SELECT T1.ORD_SEQ, T1.RNO, T1.ORD_YMD, T1.CUS_ID, T2.CUS_NM, T3.BAS_CD_NM ORD_ST_NM
    FROM T_ORD_BIG T1, M_CUS T2, C_BAS_CD T3
    WHERE T1.ORD_YMD = '20170107'
    AND T2.CUS_ID = T1.CUS_ID
    AND T3.LNG_CD = 'KO'
    AND T3.BAS_CD_DV = 'ORD_ST'
    AND T3.BAS_CD = T1.ORD_ST
    ORDER BY T1.ORD_SEQ, T1.RNO;
    ) T;

     

    이 패턴은 SQL을 추가 개발할 필요가 없어 매우 편리하다. 하지만 이와 같은 방법은 SQL 성능에 손해를 본다. 

    카운트 결과에 영향을 주지 않는 조인과 ORDER BY를 그대로 사용했기 때문이다. 

    SQL BOOSTER

     

    실행계획을 보면 두 번의 조인이 있다. 조인을 모두 수행한 후에 COUNT 처리가 되었다. 

    생각해보면 고객명과 ORD_ST 코드명, ORDER BY는 COUNT하는데 전혀 상관이 없다. 

    SELECT COUNT(*)
    FROM T_ORD_BIG T1
    WHERE T1.ORD_YMD = '20170107';

     

    이와 같이 처리해도 결과에는 아무런 영향이 없다! 따라서 COUNT시 불필요한 조인과 ORDER BY는 사용하지말자 

     

    3. 불필요한 컬럼은 사용하지 않는다.

     

    SQL을 작성하다보면, 필요한 컬럼을 일일이 적기 번거로워 SELECT *을 사용하기도 한다.

    일회성으로 실행하는 SQL이라면 SELECT *을 사용해도 특별히 문제는 없다. 하지만 실제 서비스하는 SQL이라면 꼭 필요한 컬람만 SELECT에 적어주는 것이 좋다.

     

    이는 인덱스 때문이다. 복합 인덱스를 걸어두고 *로 읽으면, TABLE ACCESS BY INDEX ROWID작업이 추가되지만, 인덱스와 동일한 컬럼만 조회하는 경우에는 해당 작업을 줄일 수 있다. 

    어느정도 TABLE ACCESS BY INDEX ROWID 작업이 발생하는 것은 성능에 큰 문제는 없지만, 줄일 수 있는 부하는 줄여주는 것이 좋으므로, 필요한 컬럼만 SELECT 절에 사용하는 습관을 가지도록 하자 

     

    4. 동일한 테이블의 반복 서브쿼리를 제거하자 

     

    SELECT절의 서브쿼리는 필요한 곳에 적절히 사용하면 SQL 성능과 가독성에 큰 도움이 된다. 

    하지만 무분별하게 사용하면 데이터베이스의 성능을 떨어뜨리는 주범이 된다. 

     

    SELECT T1.ORD_SEQ, T1.CUS_ID, T1.ORD_ST
    , (SELECT A.CUS_NM FROM M_CUS A WHERE A.CUS_ID = T1.CUS_ID) CUS_NM
    , (SELECT A.EML_DA FROM M_CUS A WHERE A.CUS_ID = T1.CUS_ID) EML_AD
    FROM T_ORD T1;

     

    고객명과 이메일 주소를 가져오기 위해 SELECT 절에 두 개의 서브쿼리를 사용했다.

    서브쿼리도 조인의 일종이다. 그러므로 위와 같이 SQL을 작성하면 M_CUS 테이블을 두 번 조인한 것과 같다.

    위 SQL은 한 번의 조인으로 변경할 수 있다.

     

    반복되는 SELECT 절 서브쿼리는 조인으로 작성하도록 하자

     

    단, 코드명과 같이 값의 종류가 많지 않은 경우 서브쿼리를 사용하는 것도 괜찮다.

          서브쿼리 캐싱으로 성능이 향상될 수 있다. 

          반복 출현하는 테이블을 무리하게 합치려다 오히려 성능이 나빠질 수도 있다. 따라서 반복 출현하는 SELET 서브쿼르는 하나로 합치는 것이 기본 원칙이지만 가장 중요한 것은 실행계획을 보고 성능에 문제가 없는지 확인하는 것이다.

     

     

     

     

     

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

    SQL BOOSTER - SQL 작성 가이드(3)  (0) 2024.07.15
    SQL BOOSTER - SQL 개발 가이드  (0) 2024.07.12
    SQL BOOSTER 페이징 기술  (0) 2024.07.11
    SQL BOOSTER - 분석함수  (0) 2024.07.10
    SQL BOOSTER - 문서번호 처리 기술  (0) 2024.07.09
Designed by Tistory.