728x90
※ SQL: Row Stream.
안녕하세요. 듀스트림입니다.
오늘은 SQL 엔진에서 하는 행 스트림 처리가 무엇인지에 대해 알아보겠습니다.
카테고리를 DBMS에 넣을지 SQL에 넣을지 고민했지만, 그냥 SQL에 넣기로 했습니다.
글을 작성하다 보면 내용보다는 의외로 이런 부분에서 로딩이 더 걸리는 것 같습니다.
SQL 엔진에서 "행 스트림(row stream)" 이란 표현은 테이블의 모든 데이터를 한꺼번에 메모리에 올려놓지 않고, 한 행(row)씩(또는 일정한 묶음 단위로) 순차적으로 읽고 전달하는 처리 방식을 말합니다.
즉, LATERAL이나 Nested Loop 같은 연산이 "행 스트림 기반(row stream based)"으로 동작한다는 건 아래처럼 이해하시면 됩니다.
1. 행 스트림 처리?
SQL의 실행 엔진은 파이프라인(pipeline) 구조로 작동합니다.
즉, 결과 집합 전체를 한 번에 계산하는 게 아니라 한 행을 읽으면 바로 다음 연산 노드로 넘기고, 다음 행을 읽는 식으로 진행합니다.
[Seq Scan on table_a]
↓ (행 단위 스트림)
[Lateral Subquery Execution]
↓
[Nested Loop Join]
↓
[Result]
이때 각 노드는 "스트림 형태"로 데이터를 전달합니다.
즉, "행 스트림(row stream)"은 결국 "조인이나 필터링이 행 단위로 흘러가는 파이프라인"을 의미합니다.
2. LATERAL과 행 스트림의 관계
LATERAL 서브쿼리는 외부 행을 하나씩 받아서 그때마다 서브쿼리를 실행합니다.
내부적으로는 아래와 같이 동작합니다:
for each outer_row in table_a (행 스트림):
inner_result = run_subquery_using(outer_row)
emit (outer_row + inner_result)
즉,
- table_a에서 한 행이 스트림으로 흘러 들어오면,
- 그 행을 인자로 사용해 LATERAL 서브쿼리를 즉시 실행하고,
- 결과를 바로 다음 노드로 흘려보냅니다.
→ 이것이 바로 "행 스트림으로 만든다", "row-by-row evaluation"이라고 부르는 동작입니다.
3. 반대 개념: 집합(materialized set) 기반 처리
LATERAL과 달리, 일반 서브쿼리나 집계는 보통 결과 집합 전체를 완성한 뒤 다음 단계로 넘깁니다.
이건 "행 스트림"이 아니라 "집합(materialized set)" 처리입니다.
예를 들어:
SELECT a.*, b.seq
FROM table_a a
JOIN (
SELECT id, seq
FROM (
SELECT id, seq,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY created DESC, seq DESC) AS rn
FROM table_b
) t
WHERE rn = 1
) b ON a.p_id = b.id;
이 경우 내부 서브쿼리 b는 전체 table_b를 다 훑어서 결과를 한꺼번에 만든 뒤, 그 완성된 테이블(=materialized set)을 조인합니다.
즉, 행 스트림처럼 한 행 단위로 바로 반응하지 않습니다.
4. 행 스트림 vs 집합 비교표
| 구분 | 행 스트림(row stream) | 집합(materialized set) |
| 대표 예시 | LATERAL, Nested Loop | Hash Join, Subquery, CTE(Materialized) |
| 평가 방식 | 외부 행마다 즉시 실행 | 전체 결과 생성 후 다음 단계로 전달 |
| 메모리 사용 | 작음 (행 단위) | 큼 (전체 결과 보관) |
| 지연 평가(Lazy Evaluation) | 가능 | 불가능 |
| 실행 효율 | 소량 행 처리 시 유리 | 대량 일괄 처리 시 유리 |
요약하자면,
"행 스트림으로 만든다"라는 말은
"LATERAL이 외부 테이블의 각 행을 받을 때마다 내부 서브쿼리를 즉시 평가해서, 결과를 스트리밍 방식으로 다음 연산에 넘긴다"라는 뜻입니다.
오늘은 여기까지~
728x90
'SQL' 카테고리의 다른 글
| SQL: 윈도우 함수 문법 구조 (0) | 2025.11.24 |
|---|---|
| SQL: 상관관계(상관 서브쿼리) (0) | 2025.10.27 |
| SQL: 실행 순서 (0) | 2025.10.24 |
| SQL: EXISTS / NOT EXISTS (0) | 2025.10.15 |
| SQL: ASC, DESC (0) | 2025.10.13 |