스키마 결합
스키마 결합 (Combining Schemas)
CSV 파일 여러 개를 한 번에 읽을 때, 파일마다 스키마(열 구조)가 서로 다르면 곤란하죠. DuckDB는 이런 경우 파일들의 스키마를 어떻게 통합해 읽는지 기준을 정해 둘 수 있어요. 이번 페이지에서 위치 기준과 이름 기준 두 가지 방식을 살펴볼게요.
출처: 공식문서
예제 (Examples)
여러 CSV 파일을 열 위치 기준으로 결합해서 읽기:
SELECT * FROM read_csv('flights*.csv');
여러 CSV 파일을 열 이름 기준으로 결합해서 읽기:
SELECT * FROM read_csv('flights*.csv', union_by_name = true);
스키마 결합이 필요한 이유
여러 파일을 읽을 때 각 파일은 자기만의 스키마를 갖고 있어서, 다른 파일과 달라질 수 있어요. 그래서 여러 파일의 스키마를 결합(combine) 하는 작업이 필요합니다. DuckDB는 이를 열 위치(by column position) 기준과 열 이름(by column name) 기준, 두 가지 방식으로 처리할 수 있어요.
기본적으로 DuckDB는 첫 번째 파일의 스키마를 읽고, 이후 파일의 열을 위치에 따라 통합합니다. 모든 파일의 스키마가 동일하다면 이 방식이 정확히 동작해요. 하지만 파일마다 스키마가 다르다면 union_by_name 옵션을 써서, 모든 파일의 열 이름을 읽어 스키마를 구성하게 할 수 있습니다.
위치 기준 통합 (Union by Position)
기본 동작은 각 파일의 열을 위치로 통합하는 것입니다. 예를 들어 두 파일 모두에서 첫 번째 열끼리, 두 번째 열끼리 합쳐지는 식이죠. 다음 두 파일을 생각해 볼게요.
flights1.csv:
FlightDate|UniqueCarrier|OriginCityName|DestCityName
1988-01-01|AA|New York, NY|Los Angeles, CA
1988-01-02|AA|New York, NY|Los Angeles, CA
flights2.csv:
FlightDate|UniqueCarrier|OriginCityName|DestCityName
1988-01-03|AA|New York, NY|Los Angeles, CA
두 파일을 동시에 읽으면 다음과 같은 결과 집합이 나옵니다.
| FlightDate | UniqueCarrier | OriginCityName | DestCityName |
|---|---|---|---|
| 1988-01-01 | AA | New York, NY | Los Angeles, CA |
| 1988-01-02 | AA | New York, NY | Los Angeles, CA |
| 1988-01-03 | AA | New York, NY | Los Angeles, CA |
이 동작은 SQL의 UNION ALL과 동일한 결과를 만듭니다.
이름 기준 통합 (Union by Name)
처리하는 파일들의 스키마가 서로 다를 때, 예를 들어 어떤 파일에 열이 추가되거나 이름이 바뀌었다면, 이번에는 이름 기준으로 통합하는 편이 낫습니다. union_by_name 옵션을 주면 되죠. 아래 예시에서 flights4.csv는 UniqueCarrier 열이 하나 더 있습니다.
flights3.csv:
FlightDate|OriginCityName|DestCityName
1988-01-01|New York, NY|Los Angeles, CA
1988-01-02|New York, NY|Los Angeles, CA
flights4.csv:
FlightDate|UniqueCarrier|OriginCityName|DestCityName
1988-01-03|AA|New York, NY|Los Angeles, CA
이 파일들을 열 이름을 위치로 통합하면서 읽으면 열 개수가 달라 오류가 나요. 반면 union_by_name 옵션을 주면 열이 올바르게 통합되고, 빠진 값은 NULL로 채워집니다.
SELECT * FROM read_csv(['flights3.csv', 'flights4.csv'], union_by_name = true);
| FlightDate | OriginCityName | DestCityName | UniqueCarrier |
|---|---|---|---|
| 1988-01-01 | New York, NY | Los Angeles, CA | NULL |
| 1988-01-02 | New York, NY | Los Angeles, CA | NULL |
| 1988-01-03 | New York, NY | Los Angeles, CA | AA |
이 동작은 SQL의 UNION ALL BY NAME과 동일합니다.
union_by_name옵션을 사용하면 메모리 소비가 늘어납니다.