파일 직접 읽기
파일 직접 읽기 (Directly Reading Files - read-file)
DuckDB는 read_text와 read_blob 함수로 파일을 파일 시스템 단계에서 바로 읽어들일 수 있어요. 각 파일의 내용을 VARCHAR 또는 BLOB으로 가져오고, 파일 크기·마지막 수정 시각 같은 메타데이터도 함께 제공해요. 이 두 함수가 핵심이라고 볼 수 있어요.
개요 (Overview)
read_text와 read_blob 함수는 파일명 하나, 파일명 목록, 또는 글로브(glob) 패턴을 인자로 받아요. 각 파일의 내용을 각각 VARCHAR 또는 BLOB 형태로 출력하고, 파일 크기와 마지막 수정 시각 같은 메타데이터도 함께 돌려줘요.
read_text
read_text 테이블 함수는 선택한 소스들을 VARCHAR로 읽어요. 각 파일은 한 행이 되고, content 필드에 해당 파일의 전체 내용이 들어가요.
SELECT size, parse_path(filename), content
FROM read_text('test/sql/table_function/files/*.txt');
| size | parse_path(filename) | content |
|---|---|---|
| 12 | [test, sql, table_function, files, one.txt] | Hello World! |
| 2 | [test, sql, table_function, files, three.txt] | 42 |
| 10 | [test, sql, table_function, files, two.txt] | Foo Bar\nFöö Bär |
DuckDB는 먼저 파일 내용이 유효한 UTF-8인지 검증해요. 만약 read_text로 유효하지 않은 UTF-8 파일을 읽으려 하면, read_blob을 쓰도록 안내하는 오류를 던져요.
read_text는 파이프(예: /dev/stdin)에서도 읽을 수 있어요.
read_text의 최대 허용 파일 크기는 3.9 GiB예요.
read_blob
read_blob 테이블 함수는 선택한 소스들을 BLOB으로 읽어요.
SELECT size, content, filename
FROM read_blob('test/sql/table_function/files/*');
| size | content | filename |
|---|---|---|
| 178 | PK\x03\x04\x0A\x00\x00\x00\x00\x00\xACi=X\x14t\xCE\xC7\x0A… | test/sql/table_function/files/four.blob |
| 12 | Hello World! | test/sql/table_function/files/one.txt |
| 2 | 42 | test/sql/table_function/files/three.txt |
| 10 | F\xC3\xB6\xC3\xB6 B\xC3\xA4r | test/sql/table_function/files/two.txt |
read_blob의 최대 허용 파일 크기는 3.9 GiB예요.
스키마 (Schema)
read_text와 read_blob이 돌려주는 테이블의 스키마는 동일해요.
DESCRIBE FROM read_text('README.md');
| column_name | column_type | null | key | default | extra |
|---|---|---|---|---|---|
| filename | VARCHAR | YES | NULL | NULL | NULL |
| content | VARCHAR | YES | NULL | NULL | NULL |
| size | BIGINT | YES | NULL | NULL | NULL |
| last_modified | TIMESTAMP | YES | NULL | NULL | NULL |
Hive 파티셔닝 (Hive Partitioning)
Hive 파티셔닝된 데이터셋에서도 읽을 수 있어요.
SELECT *
FROM read_blob('data/parquet-testing/hive-partitioning/simple/**/*.parquet')
WHERE part IN ('a', 'b') AND date >= '2012-01-01';
| filename | content | size | last_modified | date | part |
|---|---|---|---|---|---|
| …/part=a/date=2012-01-01/test.parquet | PAR1\x15\x00\x15\x14\x15\x18… | 266 | 2024-11-12 02:23:20+00 | 2012-01-01 | a |
| …/part=b/date=2013-01-01/test.parquet | PAR1\x15\x00\x15\x14\x15\x18… | 266 | 2024-11-12 02:23:20+00 | 2013-01-01 | b |
파티셔닝된 디렉터리 구조의 part와 date 값이 자동으로 컬럼으로 나오는 걸 볼 수 있어요.
메타데이터 누락 처리 (Handling Missing Metadata)
기반이 되는 파일 시스템이 이 데이터를 제공하지 못할 때(예: HTTPFS가 항상 유효한 타임스탬프를 반환하지는 않을 때), 해당 셀은 대신 NULL로 설정돼요.
프로젝션 푸시다운 지원 (Support for Projection Pushdown)
이 테이블 함수들은 불필요한 속성을 계산하지 않도록 프로젝션 푸시다운(projection pushdown) 도 사용해요. 예를 들어 대용량 파일들이 모인 디렉터리를 글로브해서 size 컬럼만 가져온다고 해볼게요. content 컬럼만 빼면 DuckDB는 파일의 실제 데이터를 읽지 않아요. 그래서 파일 크기만 빠르게 조사할 때 아주 유용하답니다.