다음을 통해 공유


자동 로더의 스키마 유추 및 진화 구성

로드된 데이터의 스키마를 자동으로 감지하도록 자동 로더를 구성하여 데이터 스키마를 명시적으로 선언하지 않고 테이블을 초기화하고, 새 열이 도입될 때 테이블 스키마를 진화시킬 수 있습니다. 이렇게 하면 시간이 지남에 따라 스키마 변경 내용을 수동으로 추적하고 적용할 필요가 없습니다.

또한 자동 로더는 JSON Blob 열에서 예기치 않은(예: 다른 데이터 형식) 데이터를 "복구"할 수 있으며, 나중에 반정형 데이터 액세스 API를 사용하여 액세스하도록 선택할 수 있습니다.

스키마 유추 및 진화를 위해 지원되는 형식은 다음과 같습니다.

파일 형식 지원되는 버전
JSON 모든 버전
CSV 모든 버전
XML Databricks Runtime 14.3 LTS 이상
Avro Databricks Runtime 10.4 LTS 이상
Parquet Databricks Runtime 11.3 LTS 이상
ORC 지원되지 않음
Text 해당 없음(고정 스키마)
Binaryfile 해당 없음(고정 스키마)

스키마 유추 및 진화에 대한 구문

cloudFiles.schemaLocation 옵션의 대상 디렉터리를 지정하면 스키마 유추 및 진화가 가능합니다. checkpointLocation에 대해 지정한 것과 동일한 디렉터리를 사용하도록 선택할 수 있습니다. Delta Live Tables를 사용하는 경우 Azure Databricks가 스키마 위치 및 기타 검사점 정보를 자동으로 관리합니다.

참고 항목

대상 테이블에 둘 이상의 원본 데이터 위치를 로드하는 경우 각 자동 로더 수집 워크로드마다 별도의 스트리밍 검사점이 필요합니다.

다음 예제에서는 cloudFiles.formatparquet를 사용합니다. 다른 파일 원본에 csv, avro 또는 json을 사용합니다. 읽기 및 쓰기에 대한 다른 모든 설정은 각 형식의 기본 동작에 대해 동일하게 유지됩니다.

Python

(spark.readStream.format("cloudFiles")
  .option("cloudFiles.format", "parquet")
  # The schema location directory keeps track of your data schema over time
  .option("cloudFiles.schemaLocation", "<path-to-checkpoint>")
  .load("<path-to-source-data>")
  .writeStream
  .option("checkpointLocation", "<path-to-checkpoint>")
  .start("<path_to_target")
)

Scala

spark.readStream.format("cloudFiles")
  .option("cloudFiles.format", "parquet")
  // The schema location directory keeps track of your data schema over time
  .option("cloudFiles.schemaLocation", "<path-to-checkpoint>")
  .load("<path-to-source-data>")
  .writeStream
  .option("checkpointLocation", "<path-to-checkpoint>")
  .start("<path_to_target")

자동 로더 스키마 유추는 어떻게 작동하나요?

자동 로더는 데이터를 처음 읽을 때 스키마를 유추하기 위해 처음 50GB 또는 1,000개 파일(둘 중 먼저 도달하는 한도)을 샘플링합니다. 자동 로더는 시간에 따른 입력 데이터에 대한 스키마 변경 내용을 추적하도록 구성된 cloudFiles.schemaLocation_schemas 디렉터리에 스키마 정보를 저장합니다.

참고 항목

사용되는 샘플의 크기를 변경하려면 SQL 구성을 다음과 같이 설정할 수 있습니다.

spark.databricks.cloudFiles.schemaInference.sampleSize.numBytes

(바이트 문자열, 예: 10gb)

spark.databricks.cloudFiles.schemaInference.sampleSize.numFiles

(정수)

기본적으로 자동 로더 스키마 유추는 형식 불일치로 인한 스키마 진화 이슈를 방지하려고 합니다. 데이터 형식(JSON, CSV 및 XML)을 인코딩하지 않는 형식의 경우 자동 로더는 모든 열을 문자열(JSON 파일의 중첩 필드 포함)으로 유추합니다. 형식화된 스키마(Parquet 및 Avro)가 있는 형식의 경우 자동 로더는 파일의 하위 집합을 샘플링하고 개별 파일의 스키마를 병합합니다. 이 동작은 다음 표에 요약되어 있습니다.

파일 형식 기본 유추 데이터 형식
JSON 문자열
CSV 문자열
XML 문자열
Avro Avro 스키마로 인코딩된 형식
Parquet Parquet 스키마로 인코딩된 형식

Apache Spark DataFrameReader는 스키마 유추에 서로 다른 동작을 사용하여 샘플 데이터를 기반으로 JSON, CSV 및 XML 원본의 열에 대한 데이터 형식을 선택합니다. 자동 로더에서 이 동작을 사용하도록 설정하려면 cloudFiles.inferColumnTypes 옵션을 true로 설정합니다.

참고 항목

CSV 데이터에 대한 스키마를 유추할 때 자동 로더는 파일에 헤더가 포함되어 있다고 가정합니다. CSV 파일에 헤더가 없는 경우 .option("header", "false") 옵션을 제공합니다. 또한 자동 로더는 샘플에 있는 모든 파일의 스키마를 병합하여 전역 스키마를 만듭니다. 그런 다음, 자동 로더는 헤더에 따라 각 파일을 읽고 CSV를 올바르게 구문 분석할 수 있습니다.

참고 항목

두 Parquet 파일에서 열에 다른 데이터 형식이 있는 경우 자동 로더는 가장 넓은 형식을 선택합니다. schemaHints를 사용하여 이 선택을 재정의할 수 있습니다. 스키마 힌트를 지정할 때 자동 로더는 열을 지정된 형식으로 캐스팅하지 않고 Parquet 판독기에서 열을 지정된 형식으로 읽도록 지시합니다. 일치하지 않는 경우 구조된 데이터 열에서 열구조됩니다.

자동 로더 스키마 진화는 어떻게 작동하나요?

자동 로더는 데이터를 처리할 때 새 열 추가를 검색합니다. 자동 로더가 새 열을 검색하면 스트림이 .로더를 사용하여 UnknownFieldException중지됩니다. 스트림에서 이 오류를 throw하기 전에 자동 로더는 데이터의 최신 마이크로 일괄 처리에 대한 스키마 유추를 수행하고, 스키마 끝에 새 열을 병합하여 스키마 위치를 최신 스키마로 업데이트합니다. 기존 열의 데이터 형식은 변경되지 않은 상태로 유지됩니다.

Databricks는 이러한 스키마가 변경된 후 자동으로 다시 시작되도록 Databricks 작업으로 자동 로더 스트림을 구성하는 것이 좋습니다.

자동 로더는 cloudFiles.schemaEvolutionMode 옵션에서 설정한 스키마 진화에 대해 다음 모드를 지원합니다.

모드 새 열을 읽는 동작
addNewColumns(기본값) 스트림이 실패합니다. 새 열이 스키마에 추가됩니다. 기존 열의 데이터 형식은 진화되지 않습니다.
rescue 스키마는 절대 진화되지 않으며 스키마 변경으로 인해 스트림이 실패하지 않습니다. 모든 새 열이 복구된 데이터 열에 기록됩니다.
failOnNewColumns 스트림이 실패합니다. 제공된 스키마가 업데이트되거나 잘못된 데이터 파일이 제거되지 않으면 스트림이 다시 시작되지 않습니다.
none rescuedDataColumn 옵션을 설정하지 않으면 스키마가 진화하지 않고 새 열이 무시되며 데이터가 복구되지 않습니다. 스키마 변경으로 인해 스트림이 실패하지 않습니다.

파티션은 자동 로더에서 어떻게 작동하나요?

데이터가 Hive 스타일 분할에 배치되는 경우 자동 로더는 데이터의 기본 디렉터리 구조에서 파티션 열을 유추하려고 시도합니다. 예를 들어 base_path/event=click/date=2021-04-01/f0.json과 같은 파일 경로는 dateevent를 파티션 열로 유추합니다. 기본 디렉터리 구조에 충돌하는 Hive 파티션이 포함되어 있거나 Hive 스타일 분할이 포함되어 있지 않으면 파티션 열이 무시됩니다.

이진 파일(binaryFile) 및 text 파일 형식에는 고정된 데이터 스키마가 있지만 파티션 열 유추가 지원됩니다. 이러한 파일 형식에는 cloudFiles.schemaLocation을 설정하는 것이 좋습니다. 이렇게 하면 잠재적인 오류 또는 정보 손실이 방지되고 자동 로더가 시작될 때마다 파티션 열이 유추되지 않습니다.

파티션 열은 스키마 진화에 고려되지 않습니다. base_path/event=click/date=2021-04-01/f0.json과 같은 초기 디렉터리 구조가 있고 새 파일을 base_path/event=click/date=2021-04-01/hour=01/f1.json으로 받기 시작하면 자동 로더가 시간 열을 무시합니다. 새 파티션 열에 대한 정보를 캡처하려면 cloudFiles.partitionColumnsevent,date,hour로 설정합니다.

참고 항목

cloudFiles.partitionColumns 옵션은 쉼표로 구분된 열 이름 목록을 받습니다. 디렉터리 구조에 key=value 쌍으로 존재하는 열만 구문 분석됩니다.

복구된 데이터 열이란?

자동 로더가 스키마를 유추하면 구조된 데이터 열이 스키마 _rescued_data에 자동으로 추가됩니다. rescuedDataColumn 옵션을 설정하여 열 이름을 바꾸거나 스키마를 제공하는 경우 열을 포함할 수 있습니다.

복구된 데이터 열은 스키마와 일치하지 않는 열이 삭제되는 대신 복구되도록 합니다. 복구된 데이터 열에는 다음과 같은 이유로 구문 분석되지 않은 데이터가 포함됩니다.

  • 스키마에 열이 없습니다.
  • 형식이 일치하지 않습니다.
  • 대/소문자가 일치하지 않습니다.

복구된 데이터 열은 복구된 열과 레코드의 원본 파일 경로를 포함하는 JSON을 포함합니다.

참고 항목

JSON 및 CSV 파서는 레코드를 구문 분석할 때 PERMISSIVE, DROPMALFORMEDFAILFAST의 세 가지 모드를 지원합니다. rescuedDataColumn과 함께 사용하면 데이터 형식 불일치로 인해 DROPMALFORMED 모드에서 레코드가 삭제되거나 FAILFAST 모드에서 오류가 throw되지 않습니다. 불완전하거나 형식이 잘못된 JSON 또는 CSV와 같은 손상된 레코드만 삭제되거나 오류가 throw됩니다. JSON 또는 CSV를 구문 분석할 때 badRecordsPath를 사용하면 rescuedDataColumn을 사용할 때 데이터 형식 불일치가 잘못된 레코드로 간주되지 않습니다. 불완전하고 형식이 잘못된 JSON 또는 CSV 레코드만 badRecordsPath에 저장됩니다.

대/소문자 구분 동작 변경

대/소문자 구분이 사용하도록 설정된 경우를 제외하고 abc, Abc, ABC 열은 동일한 열로 간주됩니다. 선택되는 경우 임의적이며 샘플링된 데이터에 따라 다릅니다. 스키마 힌트를 통해 사용해야 하는 대/소문자를 적용할 수 있습니다. 선택 항목이 만들어지고 스키마가 유추되면 자동 로더는 스키마와 일치하게 선택되지 않은 대/소문자 변형을 고려하지 않습니다.

구조된 데이터 열을 사용하도록 설정하면 스키마 이외의 사례에서 명명된 필드가 _rescued_data 열에 로드됩니다. 옵션 readerCaseSensitive를 false로 설정하여 이 동작을 변경합니다. 이 경우 자동 로더는 대/소문자를 구분하지 않는 방식으로 데이터를 읽습니다.

스키마 힌트를 사용하여 스키마 유추 재정의

스키마 힌트를 사용하여 알고 있고 필요한 스키마 정보를 유추된 스키마에 적용할 수 있습니다. 열이 특정 데이터 형식임을 알고 있거나 더 일반적인 데이터 형식(예: integer 대신 double)을 선택하려는 경우 열 데이터 형식에 대해 다음과 같은 SQL 스키마 지정 구문을 사용하는 문자열로 임의 수의 힌트를 제공할 수 있습니다.

.option("cloudFiles.schemaHints", "tags map<string,string>, version int")

지원되는 데이터 형식의 목록은 데이터 형식에 대한 설명서를 참조하세요.

스트림의 시작 부분에 열이 없으면 스키마 힌트를 사용하여 해당 열을 유추된 스키마에 추가할 수도 있습니다.

스키마 힌트를 사용하여 동작을 확인하는 유추된 스키마의 예는 다음과 같습니다.

유추된 스키마:

|-- date: string
|-- quantity: int
|-- user_info: struct
|    |-- id: string
|    |-- name: string
|    |-- dob: string
|-- purchase_options: struct
|    |-- delivery_address: string

다음 스키마 힌트를 지정합니다.

.option("cloudFiles.schemaHints", "date DATE, user_info.dob DATE, purchase_options MAP<STRING,STRING>, time TIMESTAMP")

다음과 같은 결과를 얻을 수 있습니다.

|-- date: string -> date
|-- quantity: int
|-- user_info: struct
|    |-- id: string
|    |-- name: string
|    |-- dob: string -> date
|-- purchase_options: struct -> map<string,string>
|-- time: timestamp

참고 항목

배열 및 맵 스키마 힌트 지원은 Databricks Runtime 9.1 LTS 이상에서 사용할 수 있습니다.

스키마 힌트를 사용하는 동작을 확인하기 위해 복잡한 데이터 형식이 있는 유추된 스키마의 예는 다음과 같습니다.

유추된 스키마:

|-- products: array<string>
|-- locations: array<string>
|-- users: array<struct>
|    |-- users.element: struct
|    |    |-- id: string
|    |    |-- name: string
|    |    |-- dob: string
|-- ids: map<string,string>
|-- names: map<string,string>
|-- prices: map<string,string>
|-- discounts: map<struct,string>
|    |-- discounts.key: struct
|    |    |-- id: string
|    |-- discounts.value: string
|-- descriptions: map<string,struct>
|    |-- descriptions.key: string
|    |-- descriptions.value: struct
|    |    |-- content: int

다음 스키마 힌트를 지정합니다.

.option("cloudFiles.schemaHints", "products ARRAY<INT>, locations.element STRING, users.element.id INT, ids MAP<STRING,INT>, names.key INT, prices.value INT, discounts.key.id INT, descriptions.value.content STRING")

다음과 같은 결과를 얻을 수 있습니다.

|-- products: array<string> -> array<int>
|-- locations: array<int> -> array<string>
|-- users: array<struct>
|    |-- users.element: struct
|    |    |-- id: string -> int
|    |    |-- name: string
|    |    |-- dob: string
|-- ids: map<string,string> -> map<string,int>
|-- names: map<string,string> -> map<int,string>
|-- prices: map<string,string> -> map<string,int>
|-- discounts: map<struct,string>
|    |-- discounts.key: struct
|    |    |-- id: string -> int
|    |-- discounts.value: string
|-- descriptions: map<string,struct>
|    |-- descriptions.key: string
|    |-- descriptions.value: struct
|    |    |-- content: int -> string

참고 항목

스키마 힌트는 자동 로더에 스키마를 제공하지 않는 경우에만 사용됩니다. cloudFiles.inferColumnTypes를 사용하거나 사용하지 않도록 설정하는지 여부에 관계없이 스키마 힌트를 사용할 수 있습니다.