Apache Arrow에 SQL 실행하기
Apache Arrow에 SQL 실행하기
DuckDB는 여러 종류의 Apache Arrow 객체를 쿼리할 수 있어요. 로컬 변수에 담긴 Arrow 객체를 일반 테이블처럼 SELECT로 조회할 수 있죠.
출처: 공식문서
Apache Arrow Tables
로컬 변수에 저장된 Arrow Tables는 DuckDB 안의 일반 테이블처럼 쿼리할 수 있습니다.
import duckdb
import pyarrow as pa
# connect to an in-memory database
con = duckdb.connect()
my_arrow_table = pa.Table.from_pydict({'i': [1, 2, 3, 4],
'j': ["one", "two", "three", "four"]})
# query the Apache Arrow Table "my_arrow_table" and return as an Arrow Table
results = con.execute("SELECT * FROM my_arrow_table WHERE i = 2").to_arrow_table()
Apache Arrow Datasets
변수로 저장된 Arrow Datasets도 일반 테이블처럼 쿼리할 수 있어요. Dataset은 Parquet 파일이 모인 디렉토리를 가리켜 큰 데이터셋을 분석할 때 유용합니다. DuckDB는 컬럼 선택과 행 필터를 dataset 스캔 연산 안으로 push down해서 꼭 필요한 데이터만 메모리로 가져와요.
import duckdb
import pyarrow as pa
import tempfile
import pathlib
import pyarrow.parquet as pq
import pyarrow.dataset as ds
# connect to an in-memory database
con = duckdb.connect()
my_arrow_table = pa.Table.from_pydict({'i': [1, 2, 3, 4],
'j': ["one", "two", "three", "four"]})
# create example Parquet files and save in a folder
base_path = pathlib.Path(tempfile.gettempdir())
(base_path / "parquet_folder").mkdir(exist_ok = True)
pq.write_to_dataset(my_arrow_table, str(base_path / "parquet_folder"))
# link to Parquet files using an Arrow Dataset
my_arrow_dataset = ds.dataset(str(base_path / 'parquet_folder/'))
# query the Apache Arrow Dataset "my_arrow_dataset" and return as an Arrow Table
results = con.execute("SELECT * FROM my_arrow_dataset WHERE i = 2").to_arrow_table()
Apache Arrow Scanners
변수로 저장된 Arrow Scanners도 일반 테이블처럼 쿼리할 수 있어요. Scanner는 dataset 위를 읽으며 특정 컬럼을 선택하거나 행 단위 필터를 적용합니다. DuckDB가 Arrow Dataset에 컬럼 선택·필터를 push down하는 것과 비슷하지만, 여기서는 Arrow compute 연산을 사용한다는 점이 다릅니다. Arrow는 비동기 IO로 파일에 빠르게 접근하기도 해요.
import duckdb
import pyarrow as pa
import tempfile
import pathlib
import pyarrow.parquet as pq
import pyarrow.dataset as ds
import pyarrow.compute as pc
# connect to an in-memory database
con = duckdb.connect()
my_arrow_table = pa.Table.from_pydict({'i': [1, 2, 3, 4],
'j': ["one", "two", "three", "four"]})
# create example Parquet files and save in a folder
base_path = pathlib.Path(tempfile.gettempdir())
(base_path / "parquet_folder").mkdir(exist_ok = True)
pq.write_to_dataset(my_arrow_table, str(base_path / "parquet_folder"))
# link to Parquet files using an Arrow Dataset
my_arrow_dataset = ds.dataset(str(base_path / 'parquet_folder/'))
# define the filter to be applied while scanning
# equivalent to "WHERE i = 2"
scanner_filter = (pc.field("i") == pc.scalar(2))
arrow_scanner = ds.Scanner.from_dataset(my_arrow_dataset, filter = scanner_filter)
# query the Apache Arrow scanner "arrow_scanner" and return as an Arrow Table
results = con.execute("SELECT * FROM arrow_scanner").to_arrow_table()
Apache Arrow RecordBatchReaders
Arrow RecordBatchReaders는 Arrow 스트리밍 바이너리 형식용 리더로, 일반 테이블처럼 직접 쿼리할 수 있습니다. 이 스트리밍 형식은 프로세스 간 통신이나 언어 런타임 간 통신처럼 Arrow 데이터를 주고받을 때 유용해요.
import duckdb
import pyarrow as pa
# connect to an in-memory database
con = duckdb.connect()
my_recordbatch = pa.RecordBatch.from_pydict({'i': [1, 2, 3, 4],
'j': ["one", "two", "three", "four"]})
my_recordbatchreader = pa.ipc.RecordBatchReader.from_batches(my_recordbatch.schema, [my_recordbatch])
# query the Apache Arrow RecordBatchReader "my_recordbatchreader" and return as an Arrow Table
results = con.execute("SELECT * FROM my_recordbatchreader WHERE i = 2").to_arrow_table()
더 알아보기 (Learn more)
- Arrow Table·Dataset·Scanner·RecordBatchReader 모두를 쿼리에서 직접 참조할 수 있어요.
- 반대 방향(Arrow로 내보내기)은 Export Arrow 가이드를 참고하세요.
- 파이썬 이외 클라이언트(포크/언어별. Arrow 연동)별 문서도 함께 보면 좋습니다.