Hive——SerDe

本文详细介绍了Hive反序列化的原理和应用,包括对象序列化与反序列化的过程,以及如何自定义SerDe来处理特定数据格式。通过实例展示了如何创建并使用自定义SerDe来解析特定格式的测试数据,有效节省处理海量数据的时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景

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

2、Hive的反序列化是对key/value反序列化成hive table的每个列的值。

3、Hive可以方便的将数据加载到表中而不需要对数据进行转换,这样在处理海量数据时可以节省大量的时间。

二、技术细节

1、SerDe是Serialize/Deserilize的简称,目的是用于序列化和反序列化。

2、用户在建表时可以用自定义的SerDe或使用Hive自带的SerDe,SerDe能为表指定列,且对列指定相应的数据。

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name

[(col_name data_type [COMMENT col_comment], ...)]

[COMMENT table_comment]

[PARTITIONED BY (col_name data_type

[COMMENT col_comment], ...)]

[CLUSTERED BY (col_name, col_name, ...)

[SORTED BY (col_name [ASC|DESC], ...)]

INTO num_buckets BUCKETS]

[ROW FORMAT row_format]

[STORED AS file_format]

[LOCATION hdfs_path]

创建指定SerDe表时,使用row format row_format参数,例如:

a、添加jar包。在hive客户端输入:hive>add jar /run/serde_test.jar;

或者在linux shell端执行命令:${HIVE_HOME}/bin/hive -auxpath /run/serde_test.jar

b、建表:create table serde_table row format serde 'hive.connect.TestDeserializer';

3、编写序列化类TestDeserializer。实现Deserializer接口的三个函数:

a)初始化:initialize(Configuration conf, Properties tb1)。

b)反序列化Writable类型返回Object:deserialize(Writable blob)。

c)获取deserialize(Writable blob)返回值Object的inspector:getObjectInspector()。

public interface Deserializer {

/**

* Initialize the HiveDeserializer.

* @param conf System properties

* @param tbl table properties

* @throws SerDeException

*/

public void initialize(Configuration conf, Properties tbl) throws SerDeException;

/**

* Deserialize an object out of a Writable blob.

* In most cases, the return value of this function will be constant since the function

* will reuse the returned object.

* If the client wants to keep a copy of the object, the client needs to clone the

* returned value by calling ObjectInspectorUtils.getStandardObject().

* @param blob The Writable object containing a serialized object

* @return A Java object representing the contents in the blob.

*/

public Object deserialize(Writable blob) throws SerDeException;

/**

* Get the object inspector that can be used to navigate through the internal

* structure of the Object returned from deserialize(...).

*/

public ObjectInspector getObjectInspector() throws SerDeException;

}

实现一行数据划分成hive表的time,userid,host,path四个字段的反序列化类。例如:

package hive.connect;

import java.net.MalformedURLException;

import java.net.URL;

import java.util.ArrayList;

import java.util.List;

import java.util.Properties;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.hive.serde2.Deserializer;

import org.apache.hadoop.hive.serde2.SerDeException;

import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;

import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;

import org.apache.hadoop.hive.serde2.objectinspector.-

ObjectInspectorFactory.ObjectInspectorOptions;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.io.Writable;

public class TestDeserializer implements Deserializer {

private static List<String> FieldNames = new ArrayList<String>();

private static List<ObjectInspector> FieldNamesObjectInspectors = new ArrayList<ObjectInspector>();

static {

FieldNames.add("time");

FieldNamesObjectInspectors.add(ObjectInspectorFactory

.getReflectionObjectInspector(Long.class,

ObjectInspectorOptions.JAVA));

FieldNames.add("userid");

FieldNamesObjectInspectors.add(ObjectInspectorFactory

.getReflectionObjectInspector(Integer.class,

ObjectInspectorOptions.JAVA));

FieldNames.add("host");

FieldNamesObjectInspectors.add(ObjectInspectorFactory

.getReflectionObjectInspector(String.class,

ObjectInspectorOptions.JAVA));

FieldNames.add("path");

FieldNamesObjectInspectors.add(ObjectInspectorFactory

.getReflectionObjectInspector(String.class,

ObjectInspectorOptions.JAVA));

}

@Override

public Object deserialize(Writable blob) {

try {

if (blob instanceof Text) {

String line = ((Text) blob).toString();

if (line == null)

return null;

String[] field = line.split("\t");

if (field.length != 3) {

return null;

}

List<Object> result = new ArrayList<Object>();

URL url = new URL(field[2]);

Long time = Long.valueOf(field[0]);

Integer userid = Integer.valueOf(field[1]);

result.add(time);

result.add(userid);

result.add(url.getHost());

result.add(url.getPath());

return result;

}

} catch (MalformedURLException e) {

e.printStackTrace();

}

return null;

}

@Override

public ObjectInspector getObjectInspector() throws SerDeException {

return ObjectInspectorFactory.getStandardStructObjectInspector(

FieldNames, FieldNamesObjectInspectors);

}

@Override

public void initialize(Configuration arg0, Properties arg1)

throws SerDeException {

}

}

测试HDFS上hive表数据,如下为一条测试数据:

1234567891012 123456 http://wiki.apache.org/hadoop/Hive/LanguageManual/UDF

hive> add jar /run/jar/merg_hua.jar;

Added /run/jar/merg_hua.jar to class path

hive> create table serde_table row format serde 'hive.connect.TestDeserializer';

Found class for hive.connect.TestDeserializer

OK

Time taken: 0.028 seconds

hive> describe serde_table;

OK

time bigint from deserializer

userid int from deserializer

host string from deserializer

path string from deserializer

Time taken: 0.042 seconds

hive> select * from serde_table;

OK

1234567891012 123456 wiki.apache.org /hadoop/Hive/LanguageManual/UDF

Time taken: 0.039 seconds

三、总结

1、创建Hive表使用序列化时,需要自写一个实现Deserializer的类,并且选用create命令的row format参数。

2、在处理海量数据的时候,如果数据的格式与表结构吻合,可以用到Hive的反序列化而不需要对数据进行转换,可以节省大量的时间。

### 解决 Spark SQL 中因找不到对应 Hive SerDe 导致的警告问题 在 Spark SQL 使用过程中,当尝试创建外部或将数据存储到 Hive ,可能会遇到与 Hive SerDe 不兼容的相关警告。这种现象通常发生在以下几个场景: #### 背景分析 1. **Hive MetaStore 配置不一致** 当 Spark 连接至 Hive 的 MetaStore ,如果使用的 Hive 版本或配置文件(`hive-site.xml`)未正确加载,则可能导致无法识别特定的 SerDe 类型[^1]。 2. **SerDe 注册缺失** 如果目标 Hive 数据库中的某些定义依赖于自定义或第三方提供的 SerDe 实现,而这些实现并未被当前环境所支持,则会触发类似的警告消息[^2]。 3. **Thrift 方法调用异常** 如日志所示,“Invalid method name: 'get_table_req'”,这明客户端请求的方法名称可能已过期或者服务器端版本较低而不支持该方法名。 --- #### 解决方案 ##### 1. 确认并同步 Hive 和 Spark 的版本一致性 确保运行环境中部署的 Hive 版本与 Spark 所集成的 Hive 库版本相匹配。如果不一致,可以考虑升级两者之一以达到兼容状态。例如,在较新的 Spark 发行版中,默认集成了较高版本的 Hive JAR 文件;此需调整集群内的 Hive 安装包版本来适配它。 ##### 2. 明确指定 `hive-site.xml` 通过设置参数 `-Dspark.hadoop.hive-site=...` 或者将完整的路径指向实际存在的 `hive-site.xml` 文件传入 Spark 提交命令里,从而让 Spark 正常读取必要的元数据信息以及关联的服务地址等细节。 ```bash spark-submit --conf spark.sql.warehouse.dir=/path/to/warehouse \ --files /etc/hadoop/conf/hive-site.xml \ your-application.jar ``` ##### 3. 替代默认行为——显式声明 Storage Format 对于那些引发冲突的具体格对象来说,可以选择重新设计其 Schema 并采用更广泛接受的标准格式代替原始定制化选项。比如改用 ORC、Parquet 格式的替代品而非 CSV 形态下的复杂编码逻辑: ```sql CREATE EXTERNAL TABLE IF NOT EXISTS my_external_table ( id INT, value STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE LOCATION '/data/csv'; ``` 上述例子展示了如何利用简单的分隔符文本形式保存结构化记录集合,同规避掉潜在难以处理的各种特殊序列化器需求。 ##### 4. 更新 Thrift Server API 支持范围 针对 “Invalid method name” 错误提示部分,建议核查现有 Hive MetaStore Service 是否已经开启最新 RPC 接口协议支持功能。必要情况下可参照官方文档指引完成相应补丁安装操作步骤. --- ### 总结说明 综合以上措施能够有效缓解乃至彻底消除由缺乏适当 Hive SerDe 引发的一系列告警状况。不过需要注意的是每种改动都应谨慎评估对其余业务流程的影响程度后再付诸实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值