절차 지향에서 선언형으로

절차 지향에서 선언형으로

2025. 8. 1. 23:33Tools & Skills/SQL

최근 SQL을 튜닝을 공부하면 할수록 느끼는 건데,

단순히 문법을 외우는 걸 넘어서 생각의 체계 자체를 바꾸는게 필요한 것 같다.

 

절차 지향형 vs 선언형 사고


절차지향 예시

 

SQL을 작성하면서 statement 중심의 절차 지향형 사고에 머무를 때가 많다.
쿼리를 작성하다 보면, “어떻게 이걸 구현하지?”에 초점이 맞춰진다.

 

근데 중급자 이상으로 가려면 반드시 넘어야 할 벽이 있다고 한다.
바로 expression 중심의 선언형 사고이다.

SQL은 프로그래밍 언어가 아니라, 질의(Query) 언어다.
무엇을 원하는지를 말하면, DB가 어떻게든 해준다.

 

 

UNION 쓰지 말자 (웬만하면)

  • 조건 분기 때문에 UNION을 여러 번 쓰고 있다면?
  • CASE 식으로 훨씬 자연스럽고 깔끔하게 표현할 수 있다.
  • UNION은 성능적 안티 패턴이 될 가능성이 큼 → Table Scan도 증가할 수 있음

 

 

SQL 집약(Aggregation)의 기본기

SQL은 결국 집합 지향 언어다.
GROUP BY, 집약 함수, CASE WHEN 조합만 제대로 써도 대부분의 문제를 해결할 수 있다.

CREATE TABLE NonAggTb1 (
    id VARCHAR(32) NOT NULL,        -- 고유 식별자
    data_type CHAR(1) NOT NULL,     -- A, B, C 등의 타입 구분
    data_1 INTEGER,
    data_2 INTEGER,
    data_3 INTEGER,
    data_4 INTEGER,
    data_5 INTEGER,
    data_6 INTEGER
);

 

이런 비집약 테이블이 있을 때, 각 data_type에 따라 다른 필드를 집계하고 싶다면?

 

잘못된 방식 예시

SELECT
    id,
    CASE WHEN data_type = 'A' THEN data_1 ELSE NULL END AS data_1,
    ...
FROM NonAggTb1
GROUP BY id;

 

집계 함수 없이 GROUP BY를 쓰면 오류가 난다.

 

 

MAX + CASE WHEN 활용

SELECT id,
       MAX(CASE WHEN data_type = 'A' THEN data_1 ELSE NULL END) AS data_1,
       ...
FROM NonAggTb1
GROUP BY id;

→ 이게 바로 Pivot 기법

CASE WHEN을 통해 조건 분기하고, MAX로 하나의 값으로 수렴시켜주는 구조이다.

같은 id 내에 여러 행이 있어도 MAX()는 그 중 하나를 대표값으로 만들어줌

 

 

 

실행계획과 메모리 이야기


GROUP BY는 내부적으로 어떻게 작동할까?

  • 최근 대부분의 DBMS는 Hash 알고리즘 기반 집계를 우선 사용
  • 경우에 따라 Sort 기반 집계도 사용됨

 

정렬(Sort) vs 해시(Hash)

구분 설명
정렬 (Sort) 모든 데이터를 정렬해 같은 그룹끼리 모은 뒤 집계
해시 (Hash) 해시 키를 기준으로 같은 그룹을 빠르게 모아서 집계

GROUP BY 대상의 유일성이 높을수록 해시 방식이 더 유리

 

하지만

❗ 워킹 메모리가 부족하면?

  • 정렬이든 해시든 메모리 많이 씀
  • 워킹 메모리가 부족하면 → 스왑 발생
    • 디스크를 메모리처럼 사용
    • 성능 급격히 저하

SQL 성능 = 결국 I/O 줄이기 싸움
→ 집합 사고 + 워킹 메모리 감각이 중요

 

 

합쳐서 하나, 부분의 합이 전체를 커버하는가?

이런 사고도 SQL에서는 자주 등장한다.

SELECT
    product_id
FROM PriceByAge
GROUP BY product_id
HAVING SUM(high_age - low_age + 1) = 101;

 

→ 이 상품이 0~100세까지 모든 연령을 커버하고 있는지를 합산으로 판단

이건 단순한 수치 계산을 넘어서, “집합의 완전성”을 판별하는 방법이다.

 

 

마무리하며

  • SQL은 선언형 언어
  • 생각 자체를 바꿔야 성장 가능
  • CASE WHEN, GROUP BY, MAX, HAVING 등의 조합을 자유자재로 다루는 게 핵심
  • 성능은 결국 불필요한 I/O 줄이기의 싸움
  • 메모리 부족으로 인한 스왑도 성능 병목의 핵심 원인