SerDe

SerDe

SerDe는 Serializer/Deserializer의 약자예요. Hive는 IO에 SerDe 인터페이스를 사용해요. 직렬화와 역직렬화를 모두 처리하고, 직렬화 결과를 개별 필드로 해석해 처리할 수도 있어요.

출처: 문서

본문

SerDe 개요

SerDe는 Serializer/Deserializer의 약자입니다. Hive는 IO에 SerDe 인터페이스를 사용합니다. 이 인터페이스는 직렬화와 역직렬화를 모두 처리하며, 직렬화 결과를 처리를 위한 개별 필드로 해석하는 기능도 담당합니다.

SerDe를 통해 Hive는 테이블에서 데이터를 읽고, 어떤 커스텀 형식으로든 HDFS에 다시 쓸 수 있습니다. 누구나 자신의 데이터 형식에 맞는 SerDe를 직접 작성할 수 있습니다.

SerDe에 대한 소개는 Hive SerDe를 참고하세요.

내장·커스텀 SerDe

Hive SerDe 라이브러리는 org.apache.hadoop.hive.serde2에 있습니다. (이전 SerDe 라이브러리인 org.apache.hadoop.hive.serde는 deprecated 되었습니다.)

내장 SerDe

참고: Hive 0.12 이전 릴리스의 경우 Amazon이 s3://elasticmapreduce/samples/hive-ads/libs/jsonserde.jar에서 사용 가능한 JSON SerDe를 제공합니다.

커스텀 SerDe

커스텀 SerDe에 대한 정보는 Developer Guide의 How to Write Your Own SerDe를 참고하세요.

SerDe용 HiveQL

SerDe와 그 속성을 지정하는 HiveQL 문은 Create Table(특히 Row Formats & SerDe)과 Alter Table(Add SerDe Properties)을 참고하세요.

입력 처리

  • Hive의 실행 엔진(이하 엔진)은 먼저 구성된 InputFormat을 사용해 데이터 레코드 하나를 읽습니다(InputFormat의 RecordReader가 반환하는 value 객체).
  • 엔진은 그런 다음 Serde.deserialize()를 호출해 레코드의 역직렬화를 수행합니다. 이 메서드가 반환하는 역직렬화된 객체가 실제로 완전히 역직렬화된 것이라는 실제 바인딩은 없습니다. 예를 들어 Hive에는 LazySimpleSerDe가 역직렬화된 객체를 나타내는 데 사용하는 LazyStruct 객체가 있습니다. 이 객체는 바이트를 미리 역직렬화하지 않지만 필드에 접근하는 시점에 역직렬화합니다.
  • 엔진은 또한 Serde.getObjectInspector()를 호출해 사용할 ObjectInspector를 확보합니다. 입력 데이터의 한 행을 나타내는 레코드는 본질적으로 struct 타입이므로 이것은 structObjectInspector의 하위 클래스여야 합니다.
  • 엔진은 역직렬화된 객체와 object inspector를 모든 연산자에 전달해 레코드에서 필요한 데이터를 얻는 데 사용하도록 합니다. object inspector는 역직렬화된 레코드에서 개별 필드를 구성하는 방법을 알고 있습니다. 예를 들어 StructObjectInspector는 레코드에서 특정 필드를 반환하는 getStructFieldData()라는 메서드를 갖습니다. 이것이 개별 필드에 접근하는 메커니즘입니다. 예를 들어 입력 행에서 컬럼을 추출하는 ExprNodeColumnEvaluator 클래스는 이 메커니즘을 사용해 직렬화된 행 객체에서 실제 컬럼 객체를 얻습니다. 이 실제 컬럼 객체는 차례로 (struct 같은) 복합 타입일 수 있습니다. 복합 타입 객체의 하위 필드에 접근하려면 연산자는 해당 필드와 연관된 object inspector를 사용합니다(행에 대한 최상위 StructObjectInspector가 개별 필드를 해석하는 데 사용할 수 있는 필드 수준 object inspector 목록을 유지합니다).

새 GenericUDF 추상 클래스는 UDF 인자와 연관된 ObjectInspector를 initialize() 메서드에서 제공합니다. 그래서 엔진은 먼저 이 메서드를 호출해 UDF를 초기화합니다. UDF는 그런 다음 이 ObjectInspector를 사용해 복합 인자를 해석할 수 있습니다(단순 인자의 경우 UDF에 전달되는 객체는 이미 LongWritable/IntWritable 등 올바른 기본 객체입니다).

출력 처리

출력은 입력과 유사합니다. 엔진은 레코드를 나타내는 역직렬화된 Object와 해당 ObjectInspector를 Serde.serialize()에 전달합니다. 이 맥락에서 직렬화는 레코드 객체를 쓰기를 수행하는 데 사용될 OutputFormat이 기대하는 타입의 객체로 변환하는 것을 의미합니다. 이 변환을 수행하기 위해 serialize() 메서드는 전달된 ObjectInspector를 사용해 레코드에서 개별 필드를 얻고 레코드를 적절한 타입으로 변환할 수 있습니다.

추가 참고 사항

  • 객체(행, 컬럼, 컬럼의 하위 필드, 또는 UDF의 반환 값)의 소유자는 그것을 만드는 코드이며, 객체의 수명은 다음 행에 대한 해당 객체가 만들어질 때 만료됩니다. 이는 몇 가지를 의미합니다:
    • 어떤 객체도 직접 캐시해서는 안 됩니다. group-by와 join 모두에서 객체를 복사한 다음 HashMap에 넣습니다.
    • SerDe, UDF 등은 서로 다른 행의 같은 컬럼에 대해 같은 객체를 재사용할 수 있습니다. 이는 데이터 파이프라인에서 대부분의 객체 생성을 없앨 수 있다는 뜻이며, 이는 큰 성능 향상입니다.
  • Settable ObjectInspectors(쓰기와 객체 생성용).
    • ObjectInspector는 필드를 "얻는(get)" 것을 허용하지만 필드를 "설정(set)"하거나 객체를 "생성(create)"하는 것은 허용하지 않습니다.
    • Settable ObjectInspector는 그것을 허용합니다.
    • Settable ObjectInspector의 도움으로 JavaIntObjectInspector를 가진 객체를 WritableIntObjectInspector를 가진 객체로(Integer에서 IntWritable로) 쉽게 변환할 수 있습니다.
    • UDF(GenericUDF가 아닌)에서 Java 리플렉션을 사용해 함수의 매개변수/반환 값 타입(UDFOPPlus의 경우 IntWritable 같은)을 얻은 다음, ObjectInspectorUtils.getStandardObjectInspectors로 그것에 대한 ObjectInspector를 유추합니다.
    • UDF로 전달되는 Object의 ObjectInspector와 UDF 파라미터 타입의 ObjectInspector가 주어지면 SettableObjectInspector 인터페이스를 사용해 객체를 변환하는 ObjectInspectorConverter를 구성합니다. 컨버터는 GenericUDF와 GenericUDAF에서 호출됩니다.

요약하자면, Hive는 필요하면 Integer를 IntWritable로(그 반대도) 자동 변환합니다. 이를 통해 Hadoop 지식이 없는 사람도 Java 기본 클래스(Integer 등)를 사용할 수 있고, hadoop 사용자/전문가는 더 효율적인 IntWritable을 사용할 수 있습니다.

map과 reduce 사이에서 Hive는 LazyBinarySerDe와 BinarySortableSerDe의 serialize 메서드를 사용합니다. SerDe는 ObjectInspector를 사용해 다른 serde가 만든 객체를 직렬화할 수 있습니다.

더 알아보기 (Learn more)

실제 사용 예시로는 AvroSerDeCSV SerDe 문서를 참고해요. SerDe를 커스텀으로 작성하는 방법은 개발자 가이드를 확인해 보세요.