SerDe Overview

SerDe 是 Serializer/Deserializer 的缩写。 Hive 将 SerDe 接口用于 IO。该接口既处理序列化和反序列化,又将序列化的结果解释为要处理的单个字段。

SerDe 允许 Hive 从表中读取数据,并将其以任何自定义格式写回 HDFS。任何人都可以为自己的数据格式编写自己的 SerDe。

有关 SerDes 的介绍,请参见Hive SerDe

内置和自定义 SerDes

Hive SerDe 库位于 org.apache.hadoop.hive.serde2 中。 (不建议使用 org.apache.hadoop.hive.serde 中的旧 SerDe 库.)

Built-in SerDes

注意:对于 0.12 之前的 Hive 版本,Amazon 提供了位于s3://elasticmapreduce/samples/hive-ads/libs/jsonserde.jar的 JSON SerDe。

Custom SerDes

有关自定义 SerDes 的信息,请参阅Developer Guide中的如何编写自己的 SerDe

HiveQL for SerDes

有关指定 SerDes 及其属性的 HiveQL 语句,请参见Create Table(尤其是行格式和 SerDe)和Alter Table(添加 SerDe 属性)。

Input Processing

  • Hive 的执行引擎(此后称为引擎)首先使用配置的 InputFormat 读取数据记录(由 InputFormat 的 RecordReader 返回的值对象)。

  • 然后,引擎调用 Serde.deserialize()对记录进行反序列化。没有 true 的约束,这种方法返回的反序列化对象确实是完全反序列化的对象。例如,在 Hive 中,有一个 LazyStruct 对象,LazySimpleSerDe 使用该对象表示反序列化的对象。该对象没有在前面反序列化的字节,但是在字段访问点具有。

  • 引擎还可以通过调用 Serde.getObjectInspector()来持有要使用的 ObjectInspector。这必须是 structObjectInspector 的子类,因为代表一行 Importing 数据的记录本质上是结构类型。

  • 引擎将反序列化的对象和对象检查器传递给所有操作员以供使用,以便从 Logging 获取所需的数据。对象检查器知道如何从反序列化 Logging 构造单个字段。例如,StructObjectInspector 有一个名为 getStructFieldData()的方法,该方法返回 Logging 的某个字段。这是访问各个字段的机制。例如,可以从 Importing 行提取列的 ExprNodeColumnEvaluator 类使用此机制从序列化的行对象中获取真实的列对象。该实列对象又可以是复杂类型(如 struct)。要访问此类复杂类型对象中的子字段,操作员将使用与该字段关联的对象检查器(该行的顶级 StructObjectInspector 维护可用于解释各个字段的字段级别对象检查器的列表)。

对于 UDF,新的 GenericUDF 抽象类在 initialize()方法中提供与 UDF 参数关联的 ObjectInspector。因此,引擎首先通过调用此方法来初始化 UDF。然后,UDF 可以使用这些 ObjectInspector 来解释复杂的参数(对于简单的参数,传递给 udf 的对象已经是正确的原始对象,例如 LongWritable/IntWritable 等)。

Output Processing

输出类似于 Importing。引擎将表示记录的反序列化对象和对应的 ObjectInspector 传递给 Serde.serialize()。在这种情况下,序列化意味着将记录对象转换为 OutputFormat 期望的类型的对象,该对象将用于执行写操作。要执行此转换,serialize()方法可以利用传递的 ObjectInspector 来获取 Logging 的各个字段,以便将记录转换为适当的类型。

Additional Notes

  • 对象的所有者(行,列,列的子字段或 UDF 的返回值)是创建它的代码,并且当下一个对应的对象时,对象的生存期将到期行已创建。这意味着几件事:

  • 我们不应该直接缓存任何对象。在分组和联接中,我们都复制对象,然后将其放入 HashMap 中。

    • SerDe,UDF 等可以将同一对象用于不同行中的同一列。这意味着我们可以摆脱数据管道中的大多数对象创建,这极大地提高了性能。
  • 可设置的 ObjectInspectors(用于写入和对象创建)。

  • ObjectInspector 允许我们“获取”字段,但不能“设置”字段或“创建”对象。

    • 可设置的 ObjectInspectors 允许。

    • 我们可以借助 Settable ObjectInspectors 轻松地将具有 JavaIntObjectInspector 的对象转换为具有 WritableIntObjectInspector 的对象(从 Integer 到 IntWritable)。

    • 在 UDF(非 GenericUDF)中,我们使用 Java 反射来获取函数的参数/返回值的类型(如 UDFOPPlus,则为 IntWritable),然后使用 ObjectInspectorUtils.getStandardObjectInspectors 来推断 ObjectInspector。

    • 给定传递给 UDF 的对象的 ObjectInspector 以及 UDF 参数类型的 ObjectInspector,我们将构造一个 ObjectInspectorConverter,它使用 SettableObjectInspector 接口转换该对象。转换器在 GenericUDF 和 GenericUDAF 中被称为。

简而言之,Hive 将自动转换对象,以便在需要时将 Integer 转换为 IntWritable(反之亦然)。这允许不具备 Hadoop 知识的人使用 JavaPrimitives 类(Integer 等),而 hadoop 用户/maven 可以使用 IntWritable,后者效率更高。

在 map 和 reduce 之间,Hive 使用 LazyBinarySerDe 和 BinarySortableSerDe 的序列化方法。 SerDe 可以使用 ObjectInspector 序列化由另一个 Serde 创建的对象。