DB&SQL

SQL 튜닝 - Query Transformer

초롱불 2024. 5. 26. 12:18

개요

이번 글에서는 Query Transformer에 대해서 알아보겠다. 이전 글에서 쿼리 최적화의 첫 번째 단계가 쿼리 변환이라는 것을 다루었따. 같은 결과를 반환하는 여러 쿼리가 있을 수 있지만 우리가 작성한 쿼리가 항상 최적의 것은 아니다. 쿼리 변환을 통해 오라클은 성능을 향상시키는 방향으로 쿼리를 변환하려고 시도한다. 물론 이는 쿼리의 의미를 변경하지는 않는다.

쿼리 변환의 필요성

우리가 작성한 쿼리가 항상 최적의 실행 계획을 가지고 있는 것은 아니다. 쿼리 변환기를 사용하여 오라클은 동일한 결과를 반환하지만 성능이 더 나은 쿼리로 변환한다. 하지만 이는 항상 적용되는 것은 아니며 원본 쿼리가 더 나은 경우 변환되지 않는다.

쿼리 변환 방법

오라클은 쿼리 성능을 향상시키기 위해 몇 가지 변환 방법을 사용한다. 이들 방법은 대부분의 쿼리에 대해 성능을 향상시킬 수 있다. 몇 가지 주요 변환 방법을 예시와 함께 살펴보겠다.

OR 확장(OR Expansion)

대부분의 경우 인덱스를 사용하는 것이 풀 테이블 스캔보다 훨씬 빠르다. 하지만 WHERE 절에 OR 연산자를 사용할 때, 인덱스는 사용되지 않을 수 있따. 이 경우 OR 연산자를 제거하고 AND를 사용하여 동일한 결과를 얻을 수 있다.

예시

SELECT *
FROM sales
WHERE prod_id = 123 OR promo_id = 456;
SELECT *
FROM sales
WHERE prod_id = 123
UNION ALL
SELECT *
FROM sales
WHERE promo_id = 456 AND pord_id <> 123;

변환된 쿼리는 인덱스를 사용하여 두 쿼리를 결합한 것으로 성능이 향상될 수 있다.

서브쿼리 언네스팅(Subquery Unnesting)

서브쿼리를 조인 문으로 변환하는 방법이다. 이는 동일한 데이터를 반환하면서도 성능을 향상시킬 수 있다.

예시

SELECT * 
FROM sales
WHERE cust_id IN (SELECT cust_id FROM customers);
SELECT s.*
FROM sales s
JOIN customers c ON s.cust_id = c.cust_id;

서브 쿼리를 JOIN문으로 변환하여 인덱스를 활용함으로써 성능을 향상시킨다.

변환 쿼리 사용 여부 결정

쿼리 변환기가 항상 변환된 쿼리를 사용하는 것은 아니다. 변환된 쿼리와 원래 쿼리의 비용을 비교하여 더 비용이 적은 쿼리를 선택한다. 예를 들어, 테이블이 작으면 전체 테이블 읽기를 사용하고 테이블이 크고 선택성이 높은 경우 인덱스를 사용하여 변환된 쿼리를 사용할 수 있다.

기타 변환 방법

  • 복잡한 뷰 병합
  • IN을 EXISTS로 변환
  • 필터 푸시 다운

이 외에도 다양한 변환 방법이 있으며 오라클의 공식 문서를 참조하여 더 많은 정보를 얻을 수 있다.

결론

이 글에서는 쿼리 변환기에 대해 자세히 알아보았다. 쿼리 변환기는 쿼리를 성능이 더 나은 쿼리로 변환하여 실행계획을 최적화한다. 그러나 변환된 쿼리가 항상 더 나은 것은 아니며 옵티마이저는 비용을 비교하여 최적의 쿼리를 선택한다. 이후 글에서 더 많은 예제와 함꼐 쿼리 튜닝기법을 다룰 예정이다.

감상

드디어 SQL 쿼리 예제가 나왔다. OR을 쓰면 인덱스 스캔이 안 된다는 사실을 알게 된 것만으로도 많은 것을 알게 된 것같아서 기쁘다. 이런 것도 왠만해서는 오라클 시스템에서 조정이 된다는 사실도 많은 것을 느끼게 해주는 부분이었다. 그 동안 써왔던 많은 OR 구문이 성능을 저하시켰을까 걱정이 되기도 했지만 심각한 수준의 문제는 되지 않아서 안심할 수 있었다.

'DB&SQL' 카테고리의 다른 글

SQL 튜닝 - 쿼리 비용(cost) 이해하기  (0) 2024.05.28
SQL 튜닝 - 선택성과 카디널리티  (0) 2024.05.27
SQL 튜닝 - 옵티마이저의 필요성  (0) 2024.05.25
SQL 튜닝 - SQL 실행 과정  (0) 2024.05.22
SQL 튜닝 - 파티셔닝  (0) 2024.05.21