핵심 인사이트
- 셀렉트 연산(σ, Select/Restriction)은 관계 대수의 단항 수평 필터링 연산으로, SQL WHERE 절의 수학적 기반이며 조건을 만족하는 튜플(행)만 결과 릴레이션으로 반환한다.
- 셀렉트는 가장 선택적(Selective)인 조건을 먼저 적용하면 중간 결과의 크기를 최소화할 수 있어, DBMS 옵티마이저의 핵심 최적화 규칙 중 하나인 "조건 밀어내기(Predicate Pushdown)"의 이론적 근거가 된다.
- 셀렉트 조건의 선택도(Selectivity)는 인덱스 활용 여부를 결정하는 핵심 지표로, 선택도가 낮을수록(결과 행이 적을수록) 인덱스 스캔이 유리하고 선택도가 높으면 풀 테이블 스캔이 오히려 효율적이다.
Ⅰ. 셀렉트 연산 정의
σ (Sigma, Select/Restriction):
형식: σ_조건(R)
R: 릴레이션 (테이블)
조건: 부울 표현식
조건 구성:
원자 조건: 속성 비교연산 값
예: 나이 > 25
이름 = '홍길동'
복합 조건: AND(∧), OR(∨), NOT(¬)
예: 나이 > 25 ∧ 학과 = '컴퓨터'
SQL 대응:
σ_나이>25∧학과='컴퓨터'(학생)
SELECT * FROM 학생
WHERE 나이 > 25 AND 학과 = '컴퓨터';
출력:
입력과 동일한 스키마 (동일 열)
조건 만족 행만 포함 (행 수 감소 or 동일)
📢 섹션 요약 비유: σ는 체 — 테이블이라는 큰 바구니에서 조건(체의 구멍 크기)에 맞는 알갱이(행)만 아래로 떨어진다.
Ⅱ. 셀렉트 교환법칙과 결합법칙
셀렉트의 대수 법칙:
교환법칙:
σ_c1(σ_c2(R)) = σ_c2(σ_c1(R))
조건 적용 순서 바꿔도 결과 동일
결합 (Cascade):
σ_c1(σ_c2(R)) = σ_c1∧c2(R)
두 셀렉트를 하나로 합칠 수 있음
최적화 활용:
원래: σ_나이>30(σ_학과='컴퓨터'(학생))
방법1: 학과='컴퓨터' 먼저 (인덱스 있으면 유리)
-> 결과 작은 테이블에 나이>30 적용
방법2: 나이>30 먼저 (선택도 높으면 먼저)
방법3: 결합 σ_(학과='컴퓨터')∧(나이>30)(학생)
-> 결합 인덱스 활용 가능
옵티마이저가 통계 기반으로 최적 순서 결정:
각 조건의 선택도(Selectivity) 추정
= 결과 행 수 / 전체 행 수 (0~1)
📢 섹션 요약 비유: 셀렉트 교환법칙은 두 체를 어떤 순서로 써도 결과 동일 — 순서는 효율성(속도)을 위해 바꾸는 것.
Ⅲ. 선택도와 인덱스
선택도 (Selectivity):
= 조건 만족 행 수 / 전체 행 수
0에 가까울수록 높은 선택도 (결과 작음)
인덱스 사용 기준:
선택도 낮음 (< 1~5%): Index Scan 유리
선택도 높음 (> 10~20%): Full Table Scan 유리
예시:
WHERE 학번 = '20240001' -- 선택도 ≈ 0.001% -> Index
WHERE 학년 = 1 -- 선택도 ≈ 25% -> Full Scan
인덱스 유형별 효율:
B-Tree Index: 범위, 동등 조건
나이 > 25, 이름 LIKE '홍%'
Hash Index: 동등 조건만
학번 = '20240001'
Composite Index: 다중 조건
(학과, 나이) 복합 인덱스
-> WHERE 학과='컴퓨터' AND 나이>25
실행 계획 확인:
EXPLAIN SELECT * FROM 학생 WHERE 나이 > 25;
-> Index Scan vs Full Scan 확인
📢 섹션 요약 비유: 선택도는 도서관 색인 사용 기준 — 책이 1만 권인데 한 권 찾기(선택도 낮음)는 색인 유리, 절반 찾기(높음)는 전체 훑기 빠름.
Ⅳ. Predicate Pushdown (조건 밀어내기)
Predicate Pushdown 최적화:
원리: 셀렉트 조건을 최대한 일찍(아래로) 적용
데이터량 조기 감소 -> 전체 쿼리 성능 향상
예시 쿼리:
SELECT 학생.이름, 수강.과목
FROM 학생 JOIN 수강 ON 학생.학번 = 수강.학번
WHERE 학생.학과 = '컴퓨터';
비효율적 실행:
1. 학생 × 수강 (전체 조인) - 매우 큰 결과
2. WHERE 학과='컴퓨터' 필터 - 이미 늦음
Predicate Pushdown 적용:
1. σ_학과='컴퓨터'(학생) - 학생 먼저 필터 (작아짐)
2. 작은 학생 ⋈ 수강 - 훨씬 작은 조인
분산 SQL에서:
Spark, Presto: 필터를 데이터 소스(파일 스캔)까지 내림
Parquet/ORC 컬럼 통계로 파일 단위 스킵
-> 수백 TB 데이터에서 실제로 읽는 데이터 대폭 감소
📢 섹션 요약 비유: Predicate Pushdown은 쇼핑 전에 예산 정하기 — 모든 물건을 카트에 담고 마지막에 비싼 것 빼는 것보다, 처음부터 예산 안의 것만 담기.
Ⅴ. 실무 시나리오 — 빅데이터 필터 최적화
빅데이터 환경에서 셀렉트 최적화:
데이터: S3에 저장된 10TB Parquet 파일 (주문 데이터)
쿼리: 2024년 1월 1일 이후 특정 고객의 주문
나쁜 쿼리:
SELECT * FROM orders
WHERE customer_id = 12345
AND order_date >= '2024-01-01';
(인덱스 없음, 10TB 전체 스캔)
최적화 1: 파티셔닝
order_date 컬럼으로 파티셔닝
S3 경로: s3://bucket/orders/year=2024/month=01/
-> Partition Pruning: 2024/01 이후 파티션만 스캔
-> 스캔량: 10TB -> 1TB (90% 감소)
최적화 2: 컬럼 통계 (Parquet Statistics)
각 파일 내 min/max 통계 저장
order_date 범위 조건으로 파일 스킵
-> 스캔량: 1TB -> 100GB (다시 90% 감소)
최적화 3: 블룸 필터 (Bloom Filter)
customer_id 컬럼에 블룸 필터 적용
특정 customer_id 없는 파일 스킵
-> 최종 스캔: 몇 GB 수준
결과: 10TB -> ~10GB 스캔 (1000배 성능 향상)
📢 섹션 요약 비유: 빅데이터 필터 최적화는 도서관에서 찾는 책 연도/장르/작가 순으로 범위 좁히기 — 단계별 필터링으로 찾아볼 책 수를 극적으로 줄인다.
📌 관련 개념 맵
셀렉트 연산자 (σ)
+-- 정의
| +-- 수평 필터링 (행 선택)
| +-- 단항 연산 (단일 릴레이션)
+-- 최적화
| +-- 선택도 (Selectivity)
| +-- 인덱스 (B-Tree, Hash, Composite)
| +-- Predicate Pushdown
+-- 대수 법칙
| +-- 교환법칙, 결합 (Cascade)
+-- 분산 환경
+-- Parquet 통계, Partition Pruning
+-- Bloom Filter
📈 관련 키워드 및 발전 흐름도
[관계 대수 (Codd, 1970)]
σ 셀렉트 연산 수학적 정의
|
v
[SQL WHERE 절 (1974~)]
관계 대수 → SQL 문법
|
v
[B-Tree 인덱스 (1970s)]
선택도 낮은 조건 고속 처리
|
v
[비용 기반 최적화 (1980~)]
선택도 추정 + Predicate Pushdown
|
v
[분산 SQL 엔진 (2012~)]
Parquet Column Statistics
파티션 프루닝
|
v
[현재: AI 기반 옵티마이저]
ML 기반 선택도 추정
쿼리 힌트 자동 생성
👶 어린이를 위한 3줄 비유 설명
- 셀렉트 연산은 학생 명단에서 "성적이 90점 이상인 학생만 보여줘"처럼 조건에 맞는 행만 골라내는 필터예요.
- 10만 명 중 10명을 찾을 때 인덱스를 쓰면 빠르고, 10만 명 중 5만 명을 찾을 때는 그냥 전체 훑는 게 더 빠를 수 있어요.
- 빅데이터에서는 필터 조건을 최대한 일찍 적용해서 처리할 데이터를 줄이는 게 성능의 핵심이에요!