DISTINCT는 정말 중복만 제거할까? 사용 시 주의해야 할 3가지 포인트

Posted by heoncode
2025. 4. 8. 19:48 SQL 기초 정리
728x90
반응형
SMALL

DISTINCT는 정말 중복만 제거할까? 사용 시 주의해야 할 3가지 포인트

SQL을 처음 배우거나 실무에서 데이터를 정제할 때 자주 등장하는 키워드 중 하나가 DISTINCT입니다. 보통은 "중복 제거" 용도로만 알고 있지만, 생각보다 주의할 점이 많아 잘못 쓰면 원하는 결과를 얻지 못하거나 오히려 성능이 떨어질 수 있습니다. 이번 글에서는 DISTINCT 사용 시 꼭 알아야 할 3가지 핵심 포인트를 정리해보겠습니다.

1. DISTINCT는 SELECT 절 전체 컬럼 조합의 중복을 제거합니다

많은 초보자들이 실수하는 부분입니다. DISTINCT는 단일 컬럼 기준이 아니라, SELECT 절에 명시된 전체 컬럼 조합이 동일한 경우에만 중복으로 판단합니다.

SELECT DISTINCT name, department FROM employees;

위 쿼리는 이름이 같더라도 부서가 다르면 중복으로 간주하지 않습니다. 따라서 원하는 결과가 아니라면 컬럼 선택을 신중하게 해야 합니다.

2. 정렬 순서를 바꾸면 결과는 같지만 처리 방식은 달라질 수 있습니다

DISTINCT를 사용할 때 정렬 순서는 결과값에 영향을 주진 않지만, 내부적으로 처리되는 방식은 바뀔 수 있습니다. 특히 ORDER BY를 추가하면 SQL 엔진은 정렬 연산을 추가로 수행하기 때문에 성능 차이가 날 수 있습니다.

SELECT DISTINCT department FROM employees ORDER BY department;

이처럼 DISTINCTORDER BY를 함께 사용할 때는 인덱스 활용 여부나 정렬 비용을 고려해야 합니다.

3. DISTINCT는 성능상 이슈를 유발할 수 있습니다

중복 제거는 단순해 보여도 실제로는 많은 비용이 발생할 수 있습니다. 내부적으로는 정렬(SORT) 또는 해시(HASH) 기반의 비교 연산이 일어나며, 데이터 양이 많아질수록 작업량도 크게 증가합니다.

대량의 데이터를 다룰 때는 DISTINCT보다 GROUP BY를 고려하거나, 아예 애초에 데이터가 중복되지 않도록 설계하는 것이 더 효율적일 수 있습니다.

✅ 마무리

DISTINCT는 단순한 기능이지만, 그 동작 원리를 정확히 알고 사용하지 않으면 엉뚱한 결과를 초래하거나 불필요한 성능 저하를 일으킬 수 있습니다. 실무에서는 반드시 컬럼 조합과 데이터 특성을 이해한 뒤에 신중히 사용하는 습관이 필요합니다.

#SQL #DISTINCT #중복제거 #기초문법 #SELECT문 #실무팁 #데이터정제

728x90
반응형
LIST

인덱스가 성능을 좌우한다? 속도 차이가 극명하게 나는 상황 3가지

Posted by heoncode
2025. 4. 8. 16:52 오라클 실무 쿼리 튜닝
728x90
반응형
SMALL

인덱스가 성능을 좌우한다? 속도 차이가 극명하게 나는 상황 3가지

SQL 성능 튜닝에서 인덱스(Index)는 빼놓을 수 없는 핵심 요소입니다. 하지만 단순히 인덱스를 만든다고 해서 항상 쿼리 속도가 빨라지는 것은 아닙니다. 인덱스가 실제로 효과를 발휘하는 조건과, 오히려 비효율을 유발하는 상황까지 모두 고려해야 실무에서 제대로 활용할 수 있습니다.

이번 글에서는 인덱스 유무에 따라 성능 차이가 극명하게 나는 3가지 상황을 실무 관점에서 정리해봅니다.


1. WHERE 절에서 다중 조건 필터링 시

SELECT * FROM EMPLOYEES
WHERE DEPARTMENT_ID = 10 AND JOB_ID = 'IT_PROG';

만약 DEPARTMENT_ID, JOB_ID 각각 단독 인덱스만 존재하고, 두 컬럼을 동시에 포함한 복합 인덱스가 없다면 옵티마이저는 인덱스를 비효율적으로 사용할 수 있습니다. 반면 (DEPARTMENT_ID, JOB_ID)로 구성된 복합 인덱스를 만들면 효율적인 Index Range Scan이 가능해집니다.

📌 실무 팁: 자주 함께 사용하는 조건은 복합 인덱스로 묶어주는 것이 훨씬 유리합니다.


2. 정렬(ORDER BY) + 페이징 처리 시

SELECT * FROM EMPLOYEES
ORDER BY HIRE_DATE
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;

HIRE_DATE 컬럼에 인덱스가 없으면 정렬 작업은 전 테이블을 스캔하면서 정렬 메모리를 소모하게 됩니다. 반면 인덱스가 있으면 인덱스 자체가 이미 정렬된 구조이므로 빠르게 필요한 범위만 추출할 수 있습니다.

📌 실무 팁: 페이징 쿼리에서는 정렬 기준 컬럼에 반드시 인덱스가 있어야 성능 이점을 누릴 수 있습니다.


3. 서브쿼리에서 EXISTS 조건 사용 시

SELECT * FROM DEPARTMENTS D
WHERE EXISTS (
  SELECT 1 FROM EMPLOYEES E
  WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID
);

EMPLOYEES.DEPARTMENT_ID에 인덱스가 없다면 EXISTS 서브쿼리마다 테이블을 반복 스캔하게 되어 성능 저하가 큽니다. 반면 해당 컬럼에 인덱스가 있다면 각 부서별 매칭을 빠르게 찾을 수 있어 성능이 크게 개선됩니다.

📌 실무 팁: EXISTS 또는 IN 서브쿼리에서 조인 키에 인덱스가 없으면 심각한 성능 저하가 발생할 수 있습니다.


마무리하며

인덱스는 단순히 만들어두는 것이 아니라, 쿼리 실행 계획을 고려한 설계가 중요합니다. 특히 자주 사용되는 조합, 정렬 조건, 서브쿼리의 조인 키 등을 파악해 전략적으로 인덱스를 설계하는 것이 실무 튜닝의 핵심입니다.

항상 실행 계획(EXPLAIN PLAN)을 확인하고, 인덱스가 실제로 사용되는지 검증하는 습관을 들이세요.

#오라클 #SQL #쿼리튜닝 #인덱스 #성능개선 #실무팁 #데이터베이스

728x90
반응형
LIST

오라클 쿼리 성능을 떨어뜨리는 흔한 실수: WHERE절에서 함수 사용

Posted by heoncode
2025. 4. 8. 10:19 오라클 실무 쿼리 튜닝
728x90
반응형
SMALL

오라클에서 쿼리 성능을 높이기 위해 인덱스를 적극적으로 활용하는 것이 중요합니다.
하지만 아무 생각 없이 작성한 WHERE절 하나가 인덱스를 무용지물로 만들어버릴 수 있습니다.

대표적인 실수가 바로 컬럼에 함수를 적용하여 인덱스를 타지 못하게 만드는 것입니다.
이 문제는 단순히 성능 저하로 끝나는 것이 아니라, 대용량 테이블에서는 실제 서비스 지연으로 이어질 수 있습니다.


잘못된 예시

SELECT * FROM EMP
WHERE TO_CHAR(HIREDATE, 'YYYY') = '1981';

위 쿼리는 HIREDATE 컬럼에 TO_CHAR 함수를 적용하고 있습니다.
이런 경우, 해당 컬럼에 인덱스가 걸려 있어도 인덱스를 사용할 수 없습니다.
결과적으로 오라클은 전체 테이블을 스캔(Full Table Scan) 하게 되고, 처리 시간이 급격히 늘어날 수 있습니다.


인덱스를 살리는 방법

함수는 리터럴 값(고정값)에 적용하고, 컬럼은 그대로 사용하는 것이 핵심입니다.

SELECT * FROM EMP
WHERE HIREDATE BETWEEN TO_DATE('1981-01-01', 'YYYY-MM-DD')
                  AND TO_DATE('1981-12-31', 'YYYY-MM-DD');

이 방식은 HIREDATE 컬럼에 함수가 적용되지 않기 때문에, 인덱스를 그대로 사용할 수 있습니다.
결과적으로 훨씬 빠른 조회 성능을 기대할 수 있죠.


실무에서 자주 발생하는 유사 사례

  • UPPER(컬럼) 또는 LOWER(컬럼) 으로 검색할 때
  • TRUNC(날짜컬럼)으로 날짜 비교할 때
  • 숫자 계산이 들어간 컬럼 비교 예: SALARY + BONUS > 5000

이런 경우 모두 인덱스를 못 타게 되어, 쿼리 성능이 나빠질 수 있습니다.
가능하면 계산이나 변환은 리터럴 값 쪽에 적용하도록 쿼리를 재작성하세요.


요약

  • WHERE절에서 컬럼에 함수 적용 시 인덱스를 사용할 수 없음
  • 성능을 위해 컬럼은 그대로 두고 리터럴에만 함수 사용
  • 실무에서는 사소한 실수 하나가 전체 시스템에 영향을 줄 수 있음
  • 습관처럼 인덱스를 고려한 WHERE절을 작성하는 것이 중요!

#오라클성능 #쿼리튜닝 #인덱스활용 #SQL성능최적화 #오라클쿼리 #개발팁

728x90
반응형
LIST

오라클 인덱스 스캔 방식 정리 - FULL SCAN, RANGE SCAN, UNIQUE SCAN 차이점

Posted by heoncode
2025. 4. 8. 01:32 오라클 실무 쿼리 튜닝
728x90
반응형
SMALL

오라클에서 쿼리의 성능을 결정짓는 중요한 요소 중 하나가 인덱스 사용 방식입니다. 이번 글에서는 실무에서 자주 마주치는 인덱스 스캔 방식 3가지를 정리해봅니다.


✅ 1. INDEX FULL SCAN

  • 전체 인덱스를 처음부터 끝까지 읽는 방식입니다.
  • 조건절의 범위가 넓거나, 정렬이 필요한 경우 사용됩니다.
  • 테이블 액세스 없이 인덱스에서만 데이터를 해결할 수 있는 경우 효율적일 수 있습니다.
  • 사용 예시: WHERE 절이 없고 ORDER BY만 있을 때 등

✅ 2. INDEX RANGE SCAN

  • 가장 일반적으로 사용되는 인덱스 스캔 방식입니다.
  • 조건절에 의해 특정 범위의 인덱스 값을 읽을 때 사용됩니다.
  • 주로 BETWEEN, >, <, IN, LIKE와 같은 조건이 포함될 때 발생합니다.
  • 사용 예시: WHERE age BETWEEN 20 AND 29

✅ 3. INDEX UNIQUE SCAN

  • 인덱스 컬럼이 UNIQUE이고, 조건절이 정확히 하나의 값을 지정할 때 사용됩니다.
  • 항상 최대 하나의 결과만 반환합니다.
  • 성능상 가장 빠른 인덱스 스캔 방식 중 하나입니다.
  • 사용 예시: WHERE id = 123 (id가 유니크한 경우)

🧠 실무 팁

  • 항상 인덱스를 만든다고 좋은 게 아닙니다. 테이블 구조, 조회 조건, 반환 건수 등을 고려해야 합니다.
  • SQL 실행 계획(EXPLAIN PLAN)을 통해 실제 어떤 인덱스 스캔 방식이 사용되는지 확인해보세요.

📌 마무리
인덱스 스캔 방식을 이해하고 있으면, 실행 계획을 해석할 수 있고 쿼리 튜닝 시 효과적으로 방향을 잡을 수 있습니다. 다음 글에서는 "INDEX SKIP SCAN"과 "FAST FULL SCAN" 등 잘 알려지지 않은 스캔 방식도 소개할 예정입니다.

#오라클 #SQL튜닝 #인덱스스캔 #INDEXSCAN #쿼리최적화
#DB성능 #오라클실무 #오라클튜닝 #실무SQL #개발자블로그 #티스토리블로그

728x90
반응형
LIST