https://2stndard.tistory.com/notice/203
[발간예정][EPL과 유튜브로 배우는 DuckDB] 실습 코드와 데이터
EPL과 유튜브 데이터로 배우는 DuckDB에서 사용되는 실습 데이터와 코드를 제공합니다. EPL_DATA&samplefile.zip : 책에서 사용하는 영국 프리미어리그 데이터 셋과 샘플로 사용하는 파일espn.duckdb.zip : 책
2stndard.tistory.com
Introduction
현대 데이터 엔지니어링 환경은 주로 Snowflake나 BigQuery와 같은 대규모 분산 분석 시스템이 지배하고 있습니다.
이러한 시스템들은 강력하지만, 동시에 복잡하고 비용이 높으며, 실제 대부분의 워크로드에서는 오히려 필요 이상인 경우도 많습니다.
오늘날의 많은 분석 작업은 다음과 같은 환경에서도 충분히 실행될 수 있습니다.
- 개발자의 로컬 노트북에서
- CI(Continuous Integration) 파이프라인 내부에서
- 소규모 클라우드 인스턴스에서
- 서버리스(Serverless) 함수 환경에서
그리고 점점 더 많이, 엣지(Edge) 환경에서 실행됩니다.
이러한 환경에서는 리소스가 제한적이며, 수평 확장성(horizontal scalability)보다 운영의 단순성이 훨씬 더 중요합니다.
이번 벤치마크에서는 다음 네 가지 SQL 데이터베이스를 비교합니다.
- PostgreSQL — 사실상 표준으로 자리 잡은 범용 관계형 데이터베이스(RDBMS)
- MySQL — 널리 사용되는 경량형 OLTP 중심 데이터베이스
- ClickHouse — 고성능 컬럼 기반 OLAP 엔진
- DuckDB — 현대적인 임베디드 분석 데이터베이스
이번 비교의 핵심 대상은 DuckDB입니다. DuckDB는 비교적 최근 등장한 데이터베이스이지만, MotherDuck, DuckLake와 같은 프로젝트를 통해 빠르게 주목받고 있으며, 전통적인 데이터베이스 서버보다는 분석 엔진(Analytical Engine)으로 점점 더 많이 활용되고 있습니다.
데이터 전문가라면 OLTP 데이터베이스를 사용해 분석 워크로드를 수행하는 것은 말이 안 된다고 주장할 수도 있습니다.
하지만 현실은 이상적이지 않습니다. 실제로 상당수의 분석 작업은 여전히 운영(Production) 데이터베이스에서 직접 수행되고 있습니다…!

다음 항목을 평가할 예정입니다:
- 쿼리 실행 시간
- CPU 사용량
- 메모리 사용량
측정 방법
모든 데이터베이스는 Docker 컨테이너 내부에서 실행되며, Python 기반의 벤치마크 실행기를 통해 오케스트레이션됩니다. 또한 실제 환경을 모사하기 위해 CPU 코어 수와 메모리 제한을 명시적으로 설정하여 리소스를 제한했습니다.
scenarios_full = {
"cpu": [2, 4, 6, 8, 10, 14, 18],
"mem": ["2G", "4G", "8G", "16G", "32G", "64G"],
}
중요한 제약 사항 및 해석 시 주의점
- ClickHouse는 RAM 2GB 환경에서 자주 실패했기 때문에, 해당 구간의 결과는 주의해서 해석해야 합니다.
- DuckDB는 임베디드(Embedded) 방식의 데이터베이스이므로 다음 특성을 가집니다.
- 네트워크 계층이 없음
- 클라이언트/서버 오버헤드가 없음
- 따라서 측정 가능한 의미 있는 네트워크 통계가 존재하지 않음
또한 벤치마크에서는 다음 원칙을 적용했습니다.
- ANSI SQL만 사용
- 데이터베이스 엔진별 최적화 미사용
- 고급 확장 기능 미사용 (예: 정규표현식 함수, 벤더 전용 조인 기능)
- 별도의 튜닝 없이 기본 설정 그대로 사용
이는 의도적인 선택입니다. 이번 벤치마크의 목적은 수주간의 수동 최적화 이후의 성능이 아니라, 사용자가 데이터베이스를 처음 도입했을 때 실제로 경험하게 되는 기본 동작 특성을 비교하는 데 있습니다.
데이터셋 및 쿼리 워크로드
데이터셋
이번 벤치마크에서는 Kaggle에서 제공하는 900k Spotify Songs 데이터셋을 사용했습니다.
- 크기: 1.36 GB
- 행(Row) 수: 약 900,000개
- 열(Column) 수: 39개
- 데이터셋: https://www.kaggle.com/datasets/devdope/900k-spotify/data
이 데이터셋은 분석 쿼리에 충분한 부하를 줄 만큼 규모가 크면서도, 로컬 환경이나 엣지(Edge) 환경에서 실제로 다룰 수 있는 수준의 현실적인 크기를 유지하고 있습니다.
쿼리 유형
벤치마크 워크로드는 실제 분석 환경에서 자주 사용되는 대표적인 분석 쿼리들로 구성되었습니다.
- 단순 조회(Simple Selects)
- 집계(Aggregations)
- 조인(Joins)
- 윈도우 함수(Window Functions)
이러한 유형은 실제 데이터 분석 업무에서 사용되는 대부분의 분석 시나리오를 포괄합니다.
전반적인 성능 개요 (High-Level Performance Overview)
이 섹션에서는 리소스 제한이 없는 최대 구성 환경에서의 성능을 비교합니다.
실행 환경:
- CPU: 18코어
- 메모리: 64GB RAM
실행 시간(Execution Time)은 Python 환경에서 측정했으며, CPU 및 메모리 사용량은 Docker Stats를 통해 수집했습니다.
질의 실행 시간


모든 쿼리 유형을 통틀어 보면, MySQL은 실행 시간이 눈에 띄게 높은 뚜렷한 아웃라이어(outlier) 로 나타났습니다. 이는 놀라운 결과는 아닙니다. MySQL은 기본적으로 OLTP(온라인 트랜잭션 처리) 워크로드에 최적화되어 있으며, 특히 별도의 튜닝이 없는 환경에서는 성능 저하에 민감한 특성을 보입니다.
반면 DuckDB는 전반적으로 가장 우수한 성능을 지속적으로 보여주었습니다. 특히 다음과 같은 작업에서 강점을 보였습니다.
- 조인(Joins)
- 윈도우 함수(Window Functions)
- 복합적인 분석 워크로드(Mixed Analytical Workloads)
ClickHouse와 PostgreSQL 역시 좋은 성능을 보였으며, 전반적으로 비슷한 성능 구간(performance band)에 위치했습니다.
- ClickHouse는 순수 집계(Aggregation) 작업에서 특히 뛰어난 성능을 보였고,
- PostgreSQL은 다양한 유형의 작업에서 안정적인 범용 성능을 보여주었습니다.
CPU 사용량


실행 프로파일을 살펴보면 데이터베이스마다 상당히 다른 특성을 보입니다.
- ClickHouse는 높은 처리량(Throughput)을 달성하기 위해 CPU를 매우 적극적으로 사용합니다.
- PostgreSQL은 CPU를 효율적이고 예측 가능한 방식으로 활용합니다.
- MySQL은 사용 가능한 CPU 자원을 충분히 활용하지 못하는 모습을 보입니다.
- DuckDB는 놀라울 정도로 낮은 CPU 사용량으로 높은 성능을 달성했으며, 그래프에서는 존재감이 거의 보이지 않을 정도로 작은 리소스 사용량을 나타냈습니다.
이러한 결과는 DuckDB의 벡터화 실행(Vectorized Execution) 모델과 호스트 프로세스와의 긴밀한 통합 구조가 실제 성능 측면에서 분명한 이점을 제공한다는 점을 보여줍니다.
메모리 사용량


메모리 사용량에서는 데이터베이스 간 차이가 가장 극명하게 나타났습니다.
- MySQL은 성능 대비 메모리 사용량이 매우 높은 편입니다.
- PostgreSQL은 실행 시간은 ClickHouse와 유사하지만, 더 많은 메모리를 사용하는 모습을 보였습니다.
- ClickHouse는 메모리와 CPU 사용의 균형을 비교적 잘 맞추지만, 여전히 일정 수준 이상의 기본 메모리 자원이 필요합니다.
- DuckDB는 다른 엔진들에 비해 100배에서 최대 1000배 적은 메모리만 사용했습니다.
이 결과는 DuckDB가 메모리 제약이 있는 환경에서 특히 독보적인 경쟁력을 가진다는 점을 보여줍니다. 로컬 노트북, 소규모 클라우드 인스턴스, 서버리스 환경, 엣지 컴퓨팅처럼 메모리 자원이 제한된 환경에서는 이러한 특성이 매우 큰 장점으로 작용할 수 있습니다.
네트워크 사용량

PostgreSQL, MySQL, ClickHouse의 네트워크 사용량은 대체로 비슷합니다. DuckDB는 임베디드형 데이터베이스이기 때문에 여기에는 포함되지 않았습니다.

극단적인 경우에서 나타나는 사소한 차이는 근본적인 아키텍처상의 차이보다는 드라이버 및 프로토콜 오버헤드 때문일 가능성이 높습니다.
확장성(Scaling) 동작
확장성 분석은 앞선 성능 비교와는 다른 질문에 답합니다.
리소스를 줄여갈 때 성능은 어떻게 저하되는가?
이를 분석하기 위해 3차원 표면 그래프(3D Surface Plot) 를 사용했습니다.
- X축: CPU 코어 수
- Y축: RAM 용량
- Z축: 실행 시간(Execution Time)
이 그래프를 통해 CPU와 메모리가 제한될수록 각 데이터베이스의 성능이 어떤 방식으로 변화하는지 시각적으로 확인할 수 있습니다.
또한 전체적인 추세를 더 쉽게 해석할 수 있도록 가우시안 스무딩(Gaussian Smoothing) 필터를 적용했습니다. 다만 샘플링 지점이 충분히 촘촘하지 않은 구간에서는 스무딩 과정으로 인해 일부 인공적인 패턴(Artifacts)이 나타날 수 있으므로 결과 해석 시 이를 고려해야 합니다.
PostgreSQL 스케일링

PostgreSQL은 대략 다음 지점에서 성능 저하가 본격적으로 나타납니다.
- CPU 8코어
- RAM 32GB
이 지점 아래로 내려가면 실행 시간이 다항식(polynomial) 형태로 증가합니다. 특히 메모리는 부족하지만 CPU 코어 수는 많은 구성에서 불안정성과 성능 스파이크가 관찰되었는데, 이는 실행 엔진 내부에서 메모리 압박(memory pressure)이 발생하고 있음을 시사합니다.
DuckDB 스케일링

DuckDB는 훨씬 더 이른 지점에서 최적 성능에 도달합니다.
- CPU 4코어
- RAM 8GB
리소스 압박이 있는 상황에서도 성능 저하는 대체로 선형적으로 나타나기 때문에, DuckDB는 매우 예측 가능한 성능 특성을 보입니다. 다만 CPU 14코어와 약 18GB RAM 부근에서 하나의 아티팩트가 나타났는데, 이는 테스트 편차나 스케줄링상의 예외적인 상황에서 비롯된 것으로 보입니다.
DuckDB의 작은 바이너리 크기와 최소한의 런타임 오버헤드는 일부 특수한 구성에서 스레드나 메모리 할당이 최적이 아닌 결과로 이어질 수 있습니다. 그러나 전반적인 확장성 동작은 매우 우수합니다.
ClickHouse 스케일링

ClickHouse도 DuckDB와 비슷한 최적 지점을 보입니다.
- CPU 4코어
- RAM 8GB
하지만 다음과 같은 차이가 있습니다.
- 제한된 리소스 환경에서는 실행 시간이 더 급격하게 증가합니다.
- 최대 실행 시간은 DuckDB보다 거의 2배 높습니다.
- 2GB RAM 환경에서는 여러 실행이 실패했으며, 이는 ClickHouse에 명확한 최소 메모리 한계가 있음을 보여줍니다.
특히 RAM은 부족하지만 CPU 코어 수가 많은 시나리오에서는 코어 수를 추가할수록 실행 시간이 오히려 증가했습니다. 이는 메모리 경합이 발생하는 환경에서 CPU 오버헤드가 커질 수 있음을 시사합니다.
MySQL 스케일링

MySQL은 다음과 같은 특성을 보입니다.
- 전반적으로 높은 실행 시간
- 불규칙한 확장성 동작
- 리소스 압박 상황에서 예측하기 어려운 성능
안정적으로 동작해야 할 것으로 보이는 구성에서도 설명하기 어려운 기울기와 성능 스파이크가 관찰되었습니다. 이는 MySQL이 광범위한 튜닝 없이는 분석 워크로드에 맞게 최적화하기 어렵다는 결론을 다시 한번 뒷받침합니다.
비교 및 분석
결과를 간단히 요약하면 다음과 같습니다.
- DuckDB는 매우 적은 리소스를 사용하면서도 탁월한 성능을 보여주었습니다.
- ClickHouse는 강력한 분석 성능을 제공하지만, 이를 위해 충분한 메모리 자원이 필요합니다.
- PostgreSQL은 예측 가능한 동작 특성과 함께 균형 잡힌 범용 선택지로 남아 있습니다.
- MySQL은 기본 설정 상태에서는 분석 작업 성능이 좋지 않았으며, 제한된 리소스 환경에서는 가장 적합하지 않은 선택으로 나타났습니다.
DuckDB의 성능 자체는 놀라운 결과는 아닙니다. DuckDB는 C++로 구현되었으며, 강력한 벡터화 실행(Vectorized Execution) 구조를 사용하고 있고, 애초에 분석 워크로드를 위해 설계된 데이터베이스이기 때문입니다.
하지만 이러한 설계 선택에는 분명한 트레이드오프도 존재합니다.
DuckDB가 제공하지 않는 것들
DuckDB는 의도적으로 전통적인 데이터베이스에서 흔히 제공하는 몇 가지 기능을 제외하고 있습니다.
1. 다중 사용자 보안 및 접근 제어 없음
DuckDB에는 사용자(User)나 역할(Role)에 대한 내부 개념이 없습니다. 즉, GRANT 또는 REVOKE와 같은 권한 관리 시스템이 존재하지 않습니다.
DuckDB는 서로 다른 사용자가 서로 다른 권한을 가지는 중앙 집중형 다중 테넌트(Multi-tenant) 데이터베이스로 설계되지 않았습니다.
보안은 전적으로 파일 시스템에 위임됩니다. DuckDB 문서에서도 다음과 같이 설명합니다.
데이터베이스 파일에 대한 읽기 권한이 있는 사람은 전체 데이터베이스를 읽을 수 있으며, 쓰기 권한이 있는 사람은 전체 데이터베이스를 수정할 수 있다.
2. 진정한 의미의 동시 쓰기(Concurrent Write) 지원 없음
DuckDB는 Single-Writer, Multiple-Reader(단일 쓰기, 다중 읽기) 모델을 사용합니다.
따라서 대량의 동시 쓰기를 처리해야 하는 트랜잭션 중심의 OLTP 데이터베이스를 대체하기에는 적합하지 않습니다.
대신 DuckDB는 데이터를 배치 단위로 적재하는 분석 워크로드(Analytical Workloads) 에 최적화되어 있습니다.
3. 데이터베이스 서버 또는 세션 관리 기능 없음
DuckDB에는 네트워크 연결, 클라이언트 세션, 공유 자원을 관리하는 별도의 데이터베이스 서버가 존재하지 않습니다.
설치해서 실행하는 서버 프로세스도 없으며, 애플리케이션 내부에 직접 포함되어 동작하는 인프로세스(In-process) 데이터베이스입니다.
또한 별도의 패키지 의존성 없이 라이브러리 형태로 실행됩니다.
이러한 제약들은 결함이 아니라 의도적인 설계 선택입니다.
DuckDB는 PostgreSQL이나 ClickHouse를 대체하려는 것이 아닙니다. 대신 애플리케이션, 데이터 파이프라인, 서비스 내부에 직접 내장되어 동작하는 분석 실행 엔진(Analytical Execution Engine) 으로서 강점을 발휘합니다.
최종 정리 (Final Takeaway)
다음과 같은 요구사항이 있다면:
- 다중 테넌트(Multi-tenant) 접근 환경
- 복잡한 보안 및 권한 관리 모델
- 장시간 실행되는 동시성 중심 워크로드
→ PostgreSQL 또는 ClickHouse가 더 적합한 선택입니다.
반대로 다음이 중요하다면:
- 빠른 분석 성능
- 최소한의 리소스 사용
- 운영 부담이 거의 없는 환경
- 예측 가능한 확장성
→ DuckDB는 독보적인 선택지입니다.
높은 성능을 얻기 위해 반드시 대규모 클러스터가 필요한 것은 아닙니다. 하지만 그 성능을 얻기 위해서는 문제에 맞는 올바른 도구를 선택하는 것이 중요합니다.
'EPL과 유튜브 데이터로 배우는 DuckDB' 카테고리의 다른 글
| 컬럼형 저장방식의 작동 원리 (0) | 2026.05.23 |
|---|---|
| 데이터 엔지니어를 위한 DuckDB (0) | 2026.05.22 |
| Airflow, DuckDB, Streamlit으로 StarCraft 2 데이터 탐색하기 (0) | 2026.05.20 |
| Quack: DuckDB의 클라이언트-서버 프로토콜 (0) | 2026.05.19 |
| DuckDB Tricks – Part 3 (0) | 2026.05.18 |
댓글