Materialization·Index·통계
CTAS, persistent table, zonemap, ART index, ANALYZE를 DuckDB 성능 판단으로 연결합니다.
핵심 요약
- materialization은 속도용 복사가 아니라 통계와 반복 실행을 위해 상태를 남길지 정하는 일이며, 같은 파일을 반복해서 읽거나 join 계획이 불안정하거나 CSV/JSON을 반복 읽거나 결과가 downstream 계약이면 적재 신호입니다.
- zonemap은 일반 type 컬럼에 자동 생성되어 min/max로 row group을 건너뛰므로, 자주 필터링하는 날짜·tenant·region 기준으로 ORDER BY 정렬해두면 이득이 큽니다.
- ART index는 단일 컬럼 equality·IN·constraint check에 유리하지만 DuckDB 문서상 join·aggregation·sorting 성능에는 영향을 주지 않습니다.
- VIEW는 항상 다시 계산되므로 반복 비용이 크거나 특정 시점 snapshot이 필요하면 CTAS로 table에 materialize합니다.
DuckDB에서 materialization은 "속도를 위해 복사할지"가 아니라 "통계와 반복 실행을 위해 상태를 남길지"를 정하는 일입니다. 파일을 바로 읽는 쪽이 단순하지만, 반복 join이나 복잡한 view가 많고 decompression 비용이 높거나 join order가 어긋나면 적재가 낫습니다.
Materialization 기준
| 신호 | 판단 |
|---|---|
| 같은 Parquet를 여러 번 읽는다 | DuckDB table 또는 중간 Parquet 생성 |
| join이 많고 계획이 흔들린다 | DuckDB table로 적재 후 통계 활용 |
| CSV/JSON을 반복 읽는다 | Parquet 또는 DuckDB table로 변환 |
| 결과가 downstream 계약이다 | curated Parquet로 publish |
| 탐색성 ad hoc 쿼리다 | 직접 scan 유지 |
CREATE OR REPLACE TABLE orders AS
SELECT *
FROM read_parquet('raw/orders/**/*.parquet', hive_partitioning = true);
ANALYZE orders;Zonemap
DuckDB는 일반-purpose type 컬럼에 zonemap을 자동 생성합니다. min/max 범위로 row group을 건너뛰므로, 자주 필터링하는 컬럼 기준으로 데이터가 어느 정도 정렬돼 있으면 이득이 큽니다.
CREATE OR REPLACE TABLE events_ordered AS
SELECT *
FROM events
ORDER BY event_date, tenant_id;날짜, 증가 integer, tenant, region처럼 selective filter가 반복되는 컬럼은 정렬 후보입니다.
ART index
ART index는 primary key나 unique constraint에서 암묵적으로 생기거나 CREATE INDEX로 직접 만듭니다. 다만 모든 분석 쿼리를 빠르게 해주는 만능 도구는 아닙니다.
| ART index가 유리한 경우 | 피해야 할 경우 |
|---|---|
| 단일 컬럼 equality lookup | 대규모 scan, aggregate |
IN (...) 조건 | join/aggregation/sort 가속 기대 |
| constraint check가 필요 | write-heavy table |
DuckDB 문서는 ART index가 join, aggregation, sorting 쿼리 성능에는 영향을 주지 않는다고 설명합니다.
CREATE INDEX idx_customers_id ON customers(customer_id);View와 table
CREATE OR REPLACE VIEW active_customers AS
SELECT *
FROM customers
WHERE status = 'active';
CREATE OR REPLACE TABLE active_customers_snapshot AS
SELECT *
FROM active_customers;view는 호출할 때마다 다시 계산됩니다. 반복 비용이 크거나 특정 시점 snapshot이 필요하면 table로 materialize합니다.