본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] SQL on Python (DuckDB)을 활용한 로컬 대용량 데이터 분석 가속 방법 및 Pandas와 3가지 성능 차이 해결

by Papa Martino V 2026. 4. 21.
728x90

SQL on Python (DuckDB)
SQL on Python (DuckDB)

 

 

데이터 사이언티스트와 엔지니어들이 로컬 환경에서 수십 기가바이트(GB)에 달하는 CSV나 Parquet 파일을 처리할 때 가장 먼저 마주하는 난관은 메모리 부족(OOM) 현상입니다. 전통적인 Pandas 방식은 데이터를 메모리에 모두 적재해야 하므로 대용량 데이터 처리에서 한계가 명확합니다. 이러한 문제를 혁신적으로 해결해주는 도구가 바로 '데이터베이스계의 SQLite'라 불리는 DuckDB입니다. 본 포스팅에서는 DuckDB를 활용하여 로컬 대용량 데이터 분석 속도를 10배 이상 가속하는 구체적인 방법과 Pandas와의 구조적 차이점을 심도 있게 분석합니다.


1. 왜 DuckDB인가? 대용량 데이터 분석의 패러다임 변화

DuckDB는 OLAP(Online Analytical Processing) 전용 인메모리 컬럼 기반 데이터베이스입니다. 설치가 간편하고 별도의 서버 실행이 필요 없으며, 파이썬 라이브러리처럼 호출하여 사용할 수 있다는 독창적인 장점이 있습니다.

DuckDB가 특별한 3가지 이유

  • Vectorized Query Execution: CPU 캐시를 효율적으로 사용하여 연산 속도를 극대화합니다.
  • Columnar Storage: 필요한 컬럼만 읽어오기 때문에 I/O 비용을 획기적으로 줄입니다.
  • Pandas/Arrow 통합: 복사 없이(Zero-copy) 데이터를 공유하여 메모리 효율을 극대화합니다.

2. Pandas vs DuckDB 성능 및 해석 차이 비교

실제 1,000만 행 이상의 데이터를 처리할 때 두 라이브러리가 보여주는 성능 지표와 처리 방식의 차이를 표로 정리하였습니다.

비교 항목 Pandas (DataFrame) DuckDB (SQL on Python)
처리 아키텍처 행(Row) 기반 처리 열(Columnar) 기반 처리
메모리 관리 데이터 전체를 RAM에 적재 Disk-Spilling 및 버퍼 매니저 활용
실행 속도 복잡한 집계 연산 시 상대적으로 느림 벡터화 연산으로 대용량에서 매우 빠름
대용량 파일 읽기 Chunk 단위 처리가 번거로움 자동 병렬 스캔 및 최적화 지원
SQL 지원 여부 지원하지 않음 (Pandas 문법 사용) 표준 SQL 100% 지원
리소스 점유 단일 코어 중심 작업이 많음 멀티 코어 병렬 처리가 기본값

3. 실무 개발자를 위한 DuckDB 활용 예제 (7 Examples)

개발자가 실무 현장에서 즉시 적용할 수 있도록 설계된 7가지 코드 세트입니다. 데이터 로드부터 복잡한 분석까지 다룹니다.

Example 1: CSV 파일 로드 및 SQL 쿼리 실행 (메모리 최적화)

수 GB의 CSV 파일을 로컬 메모리에 올리지 않고 SQL로 즉시 조회하는 방법입니다.


import duckdb

# 별도의 DB 서버 없이 파일 경로로 직접 SQL 실행
conn = duckdb.connect()
query = """
    SELECT * FROM read_csv_auto('large_data.csv') 
    WHERE amount > 1000 
    LIMIT 5
"""
print(conn.execute(query).df())

Example 2: Pandas DataFrame과 Zero-copy로 연동하기

이미 메모리에 있는 Pandas 데이터를 복사 비용 없이 DuckDB 엔진으로 분석하는 해결 방법입니다.


import pandas as pd
import duckdb

df = pd.DataFrame({'id': range(1000000), 'val': [i * 2 for i in range(1000000)]})

# DuckDB는 현재 스코프에 있는 Pandas 변수를 직접 참조 가능
result = duckdb.query("SELECT avg(val) FROM df").to_df()
print(result)

Example 3: 복수의 Parquet 파일 병렬 집계

와일드카드(*)를 사용하여 폴더 내 모든 Parquet 파일을 병렬로 읽어 고속 집계를 수행합니다.


import duckdb

# data 폴더 내의 모든 parquet 파일을 하나의 테이블처럼 처리
sql = """
    SELECT category, SUM(price) as total_sales
    FROM 'data/*.parquet'
    GROUP BY category
    ORDER BY total_sales DESC
"""
summary = duckdb.sql(sql).show()

Example 4: 윈도우 함수를 활용한 시계열 데이터 분석

Pandas에서 복잡한 groupby().rolling() 작업을 표준 SQL 윈도우 함수로 간결하게 구현합니다.


import duckdb

# 날짜별 누적 합계(Running Total) 계산
sql = """
    SELECT date, sales,
           SUM(sales) OVER (ORDER BY date) as running_total
    FROM sales_data
"""
# DuckDB 내장 데이터프레임 객체로 반환
rel = duckdb.sql(sql)
rel.show()

Example 5: 데이터 가공 후 로컬 DB 파일로 영구 저장

전처리가 끝난 데이터를 고효율 압축 포맷인 DuckDB 파일로 저장하여 추후 재사용하는 방법입니다.


import duckdb

# 데이터베이스 연결 및 테이블 생성
con = duckdb.connect('analytics_storage.db')
con.execute("CREATE TABLE users AS SELECT * FROM read_csv_auto('users_raw.csv')")

# 저장된 데이터 확인
con.table('users').limit(5).show()
con.close()

Example 6: 대용량 데이터에서 중복 제거 및 클렌징

고성능 SQL 엔진을 사용하여 수억 건의 데이터 중복을 제거하는 실무 패턴입니다.


import duckdb

# 중복된 로그 데이터에서 최신 로그만 추출
sql = """
    SELECT * FROM (
        SELECT *, 
               ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY timestamp DESC) as rn
        FROM 'logs/*.json'
    ) WHERE rn = 1
"""
cleaned_df = duckdb.sql(sql).df()

Example 7: Python List와의 직접 조인 연산

파이썬의 기본 자료구조와 외부 소스를 SQL 상에서 바로 결합하는 독창적인 방법입니다.


import duckdb

# 외부 매핑 데이터 (Python list of tuples)
category_map = [('A', 'Electronic'), ('B', 'Fashion')]

# DuckDB 상에서 가상 테이블로 취급하여 조인
sql = """
    SELECT t.id, m.name
    FROM raw_table t
    JOIN category_map m ON t.cat_code = m.code
"""
# register 기능을 사용하여 리스트를 테이블처럼 등록
con = duckdb.connect()
con.register('category_map', pd.DataFrame(category_map, columns=['code', 'name']))
con.execute(sql).show()

4. 대용량 분석 시 발생하는 문제 해결을 위한 팁

로컬 분석 환경에서 성능 저하를 방지하기 위해 다음 3가지 사항을 점검해야 합니다.

  1. 메모리 한도 설정: SET memory_limit='8GB'; 쿼리를 통해 시스템 전체 메모리 점유를 제어하십시오.
  2. Parquet 사용 권장: CSV보다는 컬럼 단위 읽기가 가능한 Parquet 포맷이 DuckDB와 궁합이 훨씬 좋습니다.
  3. 병렬 처리 설정: CPU 코어 수에 맞춰 SET threads=4; 등의 설정을 조절하여 병목 현상을 해결할 수 있습니다.

5. 결론 및 향후 전망

DuckDB는 데이터 엔지니어링 파이프라인과 데이터 분석 사이의 장벽을 허물고 있습니다. 이제 더 이상 로컬 분석을 위해 무거운 Spark 클러스터를 띄우거나, 메모리 부족에 시달리는 Pandas와 씨름할 필요가 없습니다. SQL의 익숙함과 Python의 유연함을 결합한 DuckDB는 2026년 현재 가장 가치 있는 로컬 데이터 도구입니다.


내용 출처 및 관련 리소스

  • Modern Data Stack: OLAP in Process (Hannes Mühleisen, Peter Boncz)
  • Python Data Science Handbook (Jake VanderPlas) 
728x90