Hive SerDe 序列化和反序列序列化表

46 篇文章 6 订阅
35 篇文章 4 订阅

一、SerDe的概念

SerDe 是两个单词的拼写 serialized(序列化) 和 deserialized(反序列化)。

对象序列化:当进程在进行远程通信时,彼此可以发送各种类型的数据,无论是什么类型的数据都会以 二进制序列的形式在网络上传送。发送方需要把对象转化为字节序列才可在网络上传输。
对象的反序列化:接收方则需要把字节序列恢复为对象。

Hive的反序列化是对key/value反序列化成hive table的每个列的值。Hive可以方便 的将数据加载到表中而不需要对数据进行转换,这样在处理海量数据时可以节省大量的时间。

二、序列化与反序列化的过程

Serializer序列化:数据行对象(Row object)—> 序列化 —> OutputFileFormate —> HDFS 文件
Deserializer反序列化:HDFS 文件 —> InputFileFormate —> 反序列化 —> 数据行对象(Row object)

三、Hive 的 SerDe 分类

1,内置 SerDe 类型

Hive 读写 HDFS 文件的 FileFormat 类型:

(1)TextInputFormat/HiveIgnoreKeyTextOutputFormat
读写文本文件格式的数据。

(2)SequenceFileInputFormat/SequenceFileOutputFormat
读写 Hadoop 的序列文件格式。

Hive 序列化和反序列化数据的SerDe 类:

(1)MetadataTypedColumnsetSerDe
用于读写以某个分隔符分隔的记录。比如使用逗号分隔符的记录(CSV),tab 键分隔符的记录。

(2)LazySimpleSerDe
默认的 SerDe 类型。读取与 MetadataTypedColumnsetSerDe 和 TCTLSeparatedProtocol 相同的数据格式,可以用这个 Hive SerDe 类型。它是以惰性的方式创建对象的,因此具有更好的性能。在 Hive 0.14.0 版本以后,在读写数据时它支持指定字符编码。
示例:

ALTER TABLE person SET SERDEPROPERTIES (‘serialization.encoding’=’GBK’)
如果把配置属性 hive.lazysimple.extended_boolean_literal 设置为 true(Hive 0.14.0 以后版本),LazySimpleSerDe 可以把 ‘T’, ‘t’, ‘F’, ‘f’,1, and0’ 视为合法的布尔字面量。而该配置默认是 false 的,因此它只会把 ‘True’ 和 ‘False’ 视为合法的布尔字面量。

(3)Thrift SerDe
读写 Thrift 序列化对象,可以使用这种 Hive SerDe 类型。需要确定的是,对于 Thrift 对象,类文件必须先被加载。

(4)动态 SerDe
为了读写 Thrift 序列化对象,我们可以使用这种 SerDe 类型。它可以理解 Thrift DDL 语句,所以对象的模式可以在运行时被提供。另外,它支持许多不同的协议,包括 TBinaryProtocol, TJSONProtocol, TCTLSeparatedProtocol。

2,自定义 SerDe 类型

如果 Hive 的自定义 Serde 类型不能满足你的需求,你可以自己定义自己的 SerDe 类型。

(1)定义一个类

定义一个类, 继承抽象类 AbstractSerDe, 实现 initialize 和 deserialize 两个方法。
示例代码如下:

package com.coder4.hive;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.serde.Constants;
import org.apache.hadoop.hive.serde2.AbstractSerDe;
import org.apache.hadoop.hive.serde2.SerDeException;
import org.apache.hadoop.hive.serde2.SerDeStats;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
public class MySerDe extends AbstractSerDe {
    // params
    private List<String> columnNames = null;
    private List<TypeInfo> columnTypes = null;
    private ObjectInspector objectInspector = null;
    // seperator
    private String nullString = null;
    private String lineSep = null;
    private String kvSep = null;
    @Override
    public void initialize(Configuration conf, Properties tbl)
            throws SerDeException {
        // Read sep
        lineSep = "\n";
        kvSep = "=";
        nullString = tbl.getProperty(Constants.SERIALIZATION_NULL_FORMAT, "");
        // Read Column Names
        String columnNameProp = tbl.getProperty(Constants.LIST_COLUMNS);
        if (columnNameProp != null && columnNameProp.length() > 0) {
            columnNames = Arrays.asList(columnNameProp.split(","));
        } else {
            columnNames = new ArrayList<String>();
        }
        // Read Column Types
        String columnTypeProp = tbl.getProperty(Constants.LIST_COLUMN_TYPES);
        // default all string
        if (columnTypeProp == null) {
            String[] types = new String[columnNames.size()];
            Arrays.fill(types, 0, types.length, Constants.STRING_TYPE_NAME);
            columnTypeProp = StringUtils.join(types, ":");
        }
        columnTypes = TypeInfoUtils.getTypeInfosFromTypeString(columnTypeProp);
        // Check column and types equals
        if (columnTypes.size() != columnNames.size()) {
            throw new SerDeException("len(columnNames) != len(columntTypes)");
        }
        // Create ObjectInspectors from the type information for each column
        List<ObjectInspector> columnOIs = new ArrayList<ObjectInspector>();
        ObjectInspector oi;
        for (int c = 0; c < columnNames.size(); c++) {
            oi = TypeInfoUtils
                    .getStandardJavaObjectInspectorFromTypeInfo(columnTypes
                            .get(c));
            columnOIs.add(oi);
        }
        objectInspector = ObjectInspectorFactory
                .getStandardStructObjectInspector(columnNames, columnOIs);
    }
    @Override
    public Object deserialize(Writable wr) throws SerDeException {
        // Split to kv pair
        if (wr == null)
            return null;
        Map<String, String> kvMap = new HashMap<String, String>();
        Text text = (Text) wr;
        for (String kv : text.toString().split(lineSep)) {
            String[] pair = kv.split(kvSep);
            if (pair.length == 2) {
                kvMap.put(pair[0], pair[1]);
            }
        }
        // Set according to col_names and col_types
        ArrayList<Object> row = new ArrayList<Object>();
        String colName = null;
        TypeInfo type_info = null;
        Object obj = null;
        for (int i = 0; i < columnNames.size(); i++) {
            colName = columnNames.get(i);
            type_info = columnTypes.get(i);
            obj = null;
            if (type_info.getCategory() == ObjectInspector.Category.PRIMITIVE) {
                PrimitiveTypeInfo p_type_info = (PrimitiveTypeInfo) type_info;
                switch (p_type_info.getPrimitiveCategory()) {
                case STRING:
                    obj = StringUtils.defaultString(kvMap.get(colName), "");
                    break;
                case LONG:
                case INT:
                    try {
                        obj = Long.parseLong(kvMap.get(colName));
                    } catch (Exception e) {
                    }
                }
            }
            row.add(obj);
        }
        return row;
    }
    @Override
    public ObjectInspector getObjectInspector() throws SerDeException {
        return objectInspector;
    }
    @Override
    public SerDeStats getSerDeStats() {
        return null;
    }
    @Override
    public Class<? extends Writable> getSerializedClass() {
        return Text.class;
    }
    @Override
    public Writable serialize(Object arg0, ObjectInspector arg1)
            throws SerDeException {
        return null;
    }
}

(2)使用自定义 Serde 类型

hive > add jar MySerDe.jar

创建表格时属性 row fromat 指定自定义的 SerDe 类。

CREATE EXTERNAL TABLE IF NOT EXISTS teacher ( 
          id BIGINT, 
          name STRING,
          age INT)
ROW FORMAT SERDE 'com.coder4.hive.MySerDe'
STORED AS TEXTFILE
LOCATION '/usr/hive/text/'

文章参考:https://www.hadoopdoc.com/hive/hive-serde

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓之以理的喵~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值