개발 메모장

[Oracle] SQL 튜닝 본문

DBMS

[Oracle] SQL 튜닝

yyyyMMdd 2023. 12. 5. 17:45
728x90

#. 다량의 데이터가 있는 테이블 또는 여러 테이블이 조인 돼있는 쿼리를 실행하면 속도가 느린 경우가 자주 발생하게 됩니다.

 

#. 쿼리가 실행될 때 최대한의 부담을 덜어줘야 DBMS도 최상의 성능을 발휘하여 우리가 원하는 값을 보여줄 것입니다.

 

#. 어떻게 해야 시스템이 부하가 걸리지 않고 빠른 응답을 할지에 대해 파악해보려 합니다.

 


1. Index 생성

    - Where, Join On, Order by 절에서 자주 사용되고 수정하지 않는 컬럼을 파악하여 생성합니다.

    - Index 생성에 사용한 컬럼은 되도록 Where 조건에 모두 사용하는 것이 좋습니다.

    - 조건절에 >=, <=, Is Null, Is Not Null, In, Not In 등의 사용을 지양하고 가능한 = 로 정확한 데이터를 조회하도록 해줍니다.

 

  • Example

- employees 테이블에 employee_id, department_id, salary 컬럼이 존재한다면 employee_id, department_id로 Index를 생성해 주는 것이 좋습니다.

- salary의 경우 월 단위 지급일 시 매달, 주 단위 지급일 시 매주 데이터가 들어오기에 적절치 않습니다.

CREATE INDEX idx_employee_id ON employees(employee_id);
CREATE INDEX idx_department_id ON employees(department_id);

2. Join이 필요 없는 경우 불필요한 조인하지 않기


    - 조인이 필요 없는 경우 조인 테이블 배제하기

SELECT A.*
FROM TABLE1 A 
INNER JOIN TABLE2 B ON A.COL1 = B.COL1
WHERE A.COL2 = 'TEST'


    - 보다시피 Join을 했지만 Table1에 대한 조건만 걸려있어 Table2에 대한 Join은 불필요합니다.


    - Table1의 Col2가 Table2에도 영향을 미처 조회해야 하는 데이터가 있는 경우엔 위와 같이 사용해야 하므로 확인을 정확히 한 뒤 필요한 내용만 추출해 조회합니다.

SELECT *
FROM TABLE1
WHERE COL2 = 'TEST'

3. 서브쿼리 최소화하기

    - 서브쿼리는 쿼리 내부에 쿼리를 사용하여 해당 값을 가져오므로 복잡한 쿼리를 사용할 때엔 유용하지만 성능을 저하시키는 원인이 됩니다.

    - 서브쿼리가 포함된 쿼리를 실행하면 두 번의 쿼리를 실행한다고 생각하면 되며 이로 인한 쿼리 처리 속도 또한 느려지게 됩니다.

SELECT *
FROM TABLE1
WHERE COL3 IN (
	SELECT COL3
    FROM TABLE2
    WHERE COL4 = 'TT'
)

 

    - 위와 같이 서브쿼리로 처리하는 방법보단 동일값을 갖는 컬럼이 양쪽 테이블 모두에 존재한다면 Join으로 처리하는 것이 좋습니다.

SELECT A.* 
FROM TABLE1 A
INNER JOIN TABLE2 B ON A.COL3 = B.COL3
WHERE A.COL4 = 'TT'

4. OR보단 And 나 IN 사용하기

SELECT *
FROM TABLE1
WHERE COL1 = 'TT' 
OR COL1 = 'EE' 
OR COL1 = 'WW'


    - 위 내용과 같이 COL1이 TT이거나 EE이거나 WW 일 경우의 데이터를 조회하게 됩니다.


    - OR은  실행 시 UNION ALL로 변환되어 실행된다고 보면 되기에 눈에 보이지 않는 불필요한 요소까지 전부 실행되므로 좋지 않습니다.


    - 차라리 IN을 사용하는 것이 더 낫습니다.

SELECT *
FROM TABLE1
WHERE COL1 IN ('TT', 'EE', 'WW');

5. IN, NOT IN보단 EXISTS, NOT EXISTS 사용하기

    - EXISTS 문을 사용하면 서브쿼리를 사용하기에 더 성능이 안 좋을 것이라 생각이 듭니다.

    - 하지만 쿼리 비용을 비교해 보면 IN을 사용했을 때가 더 많은 비용을 필요로 합니다.

    - IN : COST = 5 / EXISTS : COST = 3


6. 조건 컬럼을 원형 그대로 사용하기

    - 한마디로 좌변을 수정하는 경우는 지양해야 합니다.

    - 좌변은 테이블의 많은 데이터 원본인데 이걸 수정하면 많은 데이터를 가공한 뒤 비교하게 되므로 성능이 떨어집니다.

    - 차라리 우변을 가공하여 처리하는 것이 좋습니다.

SELECT *
FROM TABLE1
WHERE REPLACE(COL1, '-', '') = '20231205'

7. Distinct 사용하지 않기

    - 중복된 내용을 제외하고 볼 때 사용하나 그렇게 보여주기 위해 내부적으로 처리되는 작업이 있습니다.

    - 그렇기 때문에 간단히 조회하는 것 외에는 사용하지 않는 것이 좋습니다.

    - Distinct 사용 시 Cost 값이 더 높게 나옵니다.

  • Distinct 사용 시


  • Distinct 미사용 시


8. Having 조건보단 Where 조건 사용하기

    - Group by 사용할 때 조건절을 넣어야 하는 경우가 있습니다.

    - 이때 Having보단 Where에 조건을 넣는 것이 비용 측면에서 유리합니다.

    - Having 사용 실행계획을 보면 Filter를 한번 더 거치는 작업을 합니다.

    - 그렇기 때문에 Cost 값이 더 높게 나옵니다.

  • Having 사용 시


  • Where 사용 시(인덱스를 타게 되어 더 낮아짐)

 

 

===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
===========================================================

728x90