본문 바로가기
CS

SQLP

by soohykim 2025. 7. 1.
728x90
반응형

✅ SQLP

🔹 정규화 vs 비정규화

정규화 중복을 줄이고, 데이터 무결성을 유지하기 위한 DB 설계 기법. (1NF, 2NF, 3NF 등)
비정규화 성능 개선을 위해 일부러 중복 데이터를 허용하거나 테이블을 합치는 것
 

예시:
정규화된 테이블에서 JOIN이 많아 성능이 떨어지면, 일부 컬럼을 포함시켜 비정규화하여 쿼리 단순화 가능.


🔹 조인 방식

Nested Loop Join 작은 테이블 루프 돌면서 큰 테이블을 조건 검색 (인덱스 있으면 효율적)
Hash Join 조인 키를 해시로 매핑해 연결 (대용량 처리에 적합)
Merge Join 두 테이블 모두 정렬된 상태에서 병합 (정렬된 데이터에 유리)
 

👉 실행 계획(Explain Plan)을 보면 어떤 조인 방식이 사용되었는지 확인 가능.


🔹 서브쿼리 vs 인라인 뷰 vs CTE

서브쿼리 메인 쿼리 내에 포함된 SELECT (필터, 연산, 존재 여부 확인 등에 사용)
인라인 뷰 FROM 절에서 SELECT로 구성된 임시 테이블
CTE (WITH) 재사용 가능한 일시적인 쿼리 결과 집합 (가독성, 단계적 처리 유리)
 

👉 복잡한 로직은 WITH 절로 쿼리 분리 → 성능 향상 및 실행 순서 제어 가능


✅ 2. 쿼리 성능 분석

🔹 실행 계획 (Execution Plan)

  • 쿼리가 실행되는 내부 동작을 시각적으로 보여줌 (EXPLAIN PLAN)
  • 주요 지표: 실행 순서, 접근 방법 (INDEX RANGE SCAN 등), COST, ROWS
  • PLAN 분석을 통해 병목 지점 식별 가능

🔹 인덱스 스캔 방식

Full Table Scan 테이블 전체 읽기 (인덱스 부재 또는 조건 부적절)
Index Unique Scan 유니크 인덱스로 하나의 행만 조회
Index Range Scan 범위 조건 조회 (e.g., BETWEEN, <, >)
Index Skip Scan 인덱스의 선두 컬럼이 조건에 없을 때도 스캔 가능 (다중 컬럼 인덱스 활용)
 

👉 SQL 튜닝 시 Range Scan 유도, Full Scan 회피가 중요!


🔹 옵티마이저 힌트

  • RDBMS가 실행 계획을 선택하는 방식에 영향을 주는 키워드
  • 예시:
    • /*+ INDEX(tbl col_idx) */ → 특정 인덱스 강제 사용
    • /*+ USE_NL(a b) */ → Nested Loop 조인 강제
    • /*+ FULL(tbl) */ → Full Scan 강제
  • 과도한 힌트 사용은 유지보수 악화 → 필요한 경우만 제한적으로 사용

✅ 3. 성능 튜닝 전략

🔹 인덱스 설계

  • 단일 vs 복합 인덱스
  • 선두 컬럼 주의: 복합 인덱스는 첫 번째 컬럼 조건이 중요
  • 과도한 인덱스는 DML 성능 저하 유발 (INSERT/UPDATE 성능 저하)

🔹 통계 정보 (Statistics)

  • 옵티마이저가 올바른 실행 계획을 수립하기 위해 필요한 정보
  • 오래된 통계 정보 → 잘못된 계획 선택 → 성능 저하
  • 갱신 방법:
  • sql
    복사편집
    EXEC DBMS_STATS.GATHER_TABLE_STATS('SCHEMA', 'TABLE');

🔹 파티셔닝

Range Partition 날짜나 숫자 범위 기준 분할
List Partition 특정 값 목록 기준 분할 (예: 지역별)
Hash Partition 해시 함수로 균등 분할
 

👉 대용량 테이블 조회 시 PARTITION PRUNING 적용 가능 → 성능 대폭 향상


🔹 쿼리 리팩토링 기법

  • 조인 순서 변경: 필터 조건 많은 테이블 먼저 JOIN
  • 서브쿼리 분리: 조건 필터 먼저 → 결과를 JOIN
  • 필터 조건 상단 배치: WHERE 조건 먼저 평가되도록 설계
  • LIMIT/OFFSET → 성능 유의: 페이징 시 서브쿼리로 바꾸는 게 좋을 수도

✅ 4. DB 설계 및 운영 이슈

 

🔹 트랜잭션과 ACID

Atomicity 모두 성공하거나 모두 실패
Consistency 무결성 제약 조건 유지
Isolation 동시성 제어 (READ COMMITTED 등)
Durability 커밋 후 데이터 영구 보존
 

🔹 락 경합 (Lock Contention)

공유 락 (S) SELECT 시 발생, 다른 공유 락은 허용됨
배타 락 (X) UPDATE/DELETE 시 발생, 단독으로만 허용됨
데드락 서로 락을 대기하다 교착 상태 발생 → 트랜잭션 강제 종료 가능성 있음
 

🔹 배치 설계 시 고려사항

  • 작업 시간대 (리소스 부하 시기 고려)
  • 분할 처리 (Chunking)
  • 트랜잭션 범위 제한
  • 쿼리 튜닝 (특히 집계성, 조인성 배치)

✅ 요약 정리표

SQL 작성 정규화/비정규화 데이터 구조 설계
SQL 작성 조인 / 서브쿼리 / CTE 쿼리 구성 방식
성능 분석 실행 계획 / 인덱스 / 힌트 쿼리 비용 분석
튜닝 통계 정보 / 파티셔닝 / 조인 순서 변경 성능 최적화
운영 트랜잭션 / 락 / 배치 설계 운영 안정성

 

✅ 실무 적용 예시

실행 계획 (Execution Plan) 쿼리 실행 흐름과 비용 확인 도구 (EXPLAIN PLAN) 응답 지연 API에서 FULL TABLE SCAN 확인 후 인덱스 적용으로 성능 향상 (5초 → 0.9초)
인덱스 전략 단일/복합 인덱스, 인덱스 힌트 (INDEX, FULL 등) 조건절 컬럼에 맞게 복합 인덱스 설계 후 Range Scan 유도
CTE (WITH절) 활용 서브쿼리 분리 및 실행 순서 제어 리포트성 쿼리에서 JOIN 대상 미리 필터링하여 8초 → 1.3초로 단축
통계 정보 갱신 옵티마이저가 최신 데이터 기반 실행 계획 수립 DBMS_STATS 활용해 오랜 기간 미갱신된 테이블 성능 복구
조인 방식 분석 Nested Loop, Hash Join, Merge Join 소규모-대규모 테이블 조인 시 USE_NL 힌트로 적절한 실행 계획 유도
파티셔닝 Range, List, Hash 방식으로 대용량 테이블 분할 월별 매출 데이터를 파티셔닝해 배치 성능 40% 향상
 
 

📄 기술문서 작성에 적용 가능한 SQLP 기반 항목

1. 시스템 개선 제안서 내용 구성 예시

  • 현재 문제 진단: 배치 처리 1건당 평균 10초 소요
  • 원인 분석: 서브쿼리 중첩, 인덱스 미사용
  • 개선안:
    • CTE로 분리하여 실행 흐름 정리
    • DBMS_STATS로 통계 최신화
    • 복합 인덱스 적용 및 USE_NL 힌트 적용
  • 개선 효과: 전체 배치 시간 3시간 → 50분 단축

2. 배치 성능 이슈 대응 문서 포맷

  • 일시: 2025.06.01
  • 대상: 주문 테이블
  • 이슈: FULL TABLE SCAN으로 인해 일시적 부하
  • 조치:
    • 인덱스 추가
    • WHERE 절 조건 재배치
    • 테스트 결과: 평균 처리 시간 6.3초 → 1.2초로 단축
 
전략 설명
서브쿼리 분리 조건 필터링을 외부로 빼서 먼저 처리
조인 순서 변경 필터 조건이 많은 테이블을 먼저 조인
인덱스 힌트 활용 옵티마이저가 잘못된 계획 선택 시 개입
집계 필터 선적용 HAVING 대신 서브쿼리로 미리 필터링
데이터 양 줄이기 DISTINCT, COUNT 연산 전 WHERE 절 우선 적용

🧠 개념별 실전 SQL 예제

예제 1: CTE로 쿼리 분리

WITH recent_orders AS (
  SELECT user_id FROM orders WHERE order_date >= '2024-01-01'
)
SELECT u.user_id, COUNT(*)
FROM users u
JOIN recent_orders r ON u.user_id = r.user_id
GROUP BY u.user_id;

예제 2: 통계 갱신

EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'ORDERS');

예제 3: 힌트 적용

SELECT /*+ INDEX(o orders_user_idx) */ *
FROM orders o
WHERE user_id = 'A100';
 
 
 

❓ 면접에서 자주 나오는 SQLP 관련 질문 & 답변 예시

Q1. SQL 튜닝을 어떻게 했는지 사례를 말해보세요.

A. "리스크 보고서 조회 API가 느려서, 실행 계획을 분석한 결과 Full Scan이 발생하고 있었습니다. 통계 정보를 갱신하고 복합 인덱스를 생성해 성능을 개선했고, 결과적으로 5.3초 걸리던 응답이 0.9초로 단축됐습니다."

Q2. CTE와 서브쿼리의 차이점은?

A. "CTE는 WITH절을 사용해 쿼리를 명시적으로 분리할 수 있으며, 실행 순서가 명확해져서 성능 튜닝과 가독성에 유리합니다. 특히 재귀 쿼리나 복잡한 조인 구조 분해에 효과적입니다."

Q3. 통계 정보가 중요한 이유는?

A. "DBMS 옵티마이저가 실행 계획을 선택할 때 테이블의 데이터 분포 정보를 기준으로 합니다. 오래된 통계 정보는 잘못된 조인 방식이나 풀스캔을 유발할 수 있기 때문에, 주기적인 갱신이 필요합니다."

Q4. 인덱스를 사용했는데도 느리다면?

A. "쿼리 조건이 인덱스의 선두 컬럼과 일치하지 않거나, 통계 정보가 부정확해서 옵티마이저가 인덱스를 무시할 수 있습니다. 실행 계획을 확인하고, 힌트나 인덱스 재설계를 검토해야 합니다."

 

 

🟡 [상황]

신한투자증권 리스크관리 시스템에서 특정 보고서 조회 API가
평균 5~6초 이상 소요되고, 사용자가 “응답 없음” 오류를 경험함.


🟡 [문제 분석]

  • LEFT JOIN이 많은 복잡한 뷰를 기반으로 함
  • 테이블 3개 이상에서 FULL TABLE SCAN 발생
  • EXPLAIN PLAN 분석 결과, WHERE 절 필터 조건이 인덱스에 반영되지 않음
  • 통계 정보가 오래되어 옵티마이저가 잘못된 실행 계획 선택

🟡 [해결 조치]

  1. 통계 정보 최신화:
    DBMS_STATS.GATHER_TABLE_STATS로 통계 재수집
    → 옵티마이저가 최신 데이터 분포 기반으로 실행 계획 선택 가능
  2. 인덱스 설계 및 생성:
    리스크 구분, 기준일, 계좌번호에 복합 인덱스 생성
    → 조건절 필터에 맞춰 효율적인 Range Scan 유도
  3. 쿼리 리팩토링:
    • 불필요한 서브쿼리 제거
    • OUTER JOIN → INNER JOIN으로 변경
    • 필터 조건을 가능한 상단으로 이동
  4. **뷰에서 CTE(Common Table Expression)**로 재작성하여 가독성 개선

🟡 [결과]

  • 응답 시간 5.2초 → 0.9초로 단축
  • 배치도 동일한 방식으로 쿼리 최적화 진행하여 전체 실행 시간 약 40% 단축
  • 팀 내 공유 문서로 작성하여 유사 케이스 참고자료로 사용됨

 

“SQLP 자격증을 준비하면서 Execution Plan 해석이나 인덱스 전략을 집중적으로 학습했습니다.
이를 실무에 적용해, 신한투자증권 프로젝트에서 특정 리스크 보고서 쿼리가 5초 넘게 걸리던 문제를 해결했습니다.
EXPLAIN PLAN을 분석해 인덱스 미사용과 비효율적인 JOIN 구조를 파악했고,
통계 정보 최신화, 복합 인덱스 설계, 조건절 재배치, OUTER JOIN 제거 등으로 튜닝했습니다.
최종적으로 API 응답 시간이 0.9초로 줄었고, 사용자 오류 신고도 사라졌습니다.
SQLP 학습이 실무 튜닝에 직접 연결되었던 경험이었습니다.”

 

728x90
반응형

'CS' 카테고리의 다른 글

금융 보안  (1) 2025.07.02
React  (0) 2025.07.01
퇴직연금  (5) 2025.06.30
코드 관리  (1) 2025.06.27
배치 개발  (0) 2025.06.27