关于hive RegexSerDe的源码分析

简介:

  最近有个业务建表使用了 RegexSerDe,之前虽然也它来解析nginx日志,但是没有做深入的了解。这次看了下其实现方式。

建表语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE external TABLE ods_cart_log
(
time_local STRING,
request_json  STRING,
trace_id_num STRING
)
PARTITIONED BY
(
dt string,
hour string
)
ROW FORMAT SERDE  'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES
( "input.regex"  =
"\\\[(.*?)\\\] .*\\\|(.*?) (.*?) \\\[(.*?)\\\]" ,
"output.format.string"  = "%1$s %2$s  %4$s" )
STORED AS TEXTFILE;

测试数据:

1
2
3
4
5
[2014-07-24 15:54:54] [6] OperationData.php: 
:89|{ "action" : "add" , "redis_key_hash" :9, "time" : "1406188494.73745500" , "source" : "web" ,
"mars_cid" : "" , "session_id" : "" , "info" :{ "cart_id" :26885, "user_id" :4, "size_id" : "2784145" ,
"num" : "1" , "warehouse" : "VIP_NH" , "brand_id" : "7379" , "cart_record_id" :26885, "channel" : "te" }}
  trace_id [40618849399972881308]

这里trace_id_num按照猜想应该是第4个字段(即40618849399972881308),但是实际输出了第3个字段(trace_id)

查看其代码实现:

RegexSerDe主要由下面三个参数:

1)input.regex 正则

2)output.format.string 输出格式

3)input.regex.case.insensitive  大小写是否敏感

其中input.regex用在反序列化方法中,即数据的读取(hive读取hdfs文件),相对的output.format.string 用在序列化的方法中,即数据的写入(hive写入hdfs文件)。

在反序列化的方法deserialize中有如下代码,用于返回代表匹配字段的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    for  ( int  c =  0 ; c < numColumns; c++) {    //numColumns是按表中column的数量算的(
    比如这个例子columnNames 是[time_local, request_json, trace_id_num]   | numColumns = columnNames.size();
       try  {
         row.set(c, m.group(c +  1 ));   //可以看到字段的匹配从0开始,中间不会有跳跃,
         所以这里select  trace_id_num 字段是正则里面的第 3 个组,而和output.format.string没有关系
           catch  (RuntimeException e) {
         partialMatchedRows++;
         if  (partialMatchedRows >= nextPartialMatchedRows) {
           nextPartialMatchedRows = getNextNumberToDisplay(nextPartialMatchedRows);
           // Report the row
           LOG.warn( ""  + partialMatchedRows
               " partially unmatched rows are found, "  " cannot find group "
               + c +  ": "  + rowText);
         }
         row.set(c,  null );
       }
     }

  work around的方法有两个,1个是把所有正则匹配的字段列出,另一个就是更改正则的分组,只拿自己care的分组,比如上面可以改为

1
\\\[(.*?)\\\] .*\\\|(.*?) .*? \\\[(.*?)\\\]

  这里output.format.string的设置仔细想想貌似没什么用,首先RegexSerDe的方式只在textfile下生效,即可以用load向hive的表中导入数据,但是load是一个hdfs层面的文件操作,不涉及到序列化,如果想使用序列化,需要使用insert into select的方式插入数据,但是这种方式插入的数据又和select的数据有关系,和output.format.string没什么关系了。。

其实regexserde类有两个

分别位于

1
./serde/src/java/org/apache/hadoop/hive/serde2/RegexSerDe.java 和
1
./contrib/src/java/org/apache/hadoop/hive/contrib/serde2/RegexSerDe.java

都是扩展了AbstractSerDe这个抽象类。通过代码可以看到contrib下的这个类是实现了serialize 和 deserialize 方法,而上面这个只实现了deserialize 方法,由此看来RegexSerDe中的serialize 方法可能是没什么用的。。

另外需要注意几点:

1.如果一行匹配不上,整个行的字段输出都是null

1
2
3
4
5
6
7
8
9
  if  (!m.matches()) {
       unmatchedRows++;
       if  (unmatchedRows >= nextUnmatchedRows) {
         nextUnmatchedRows = getNextNumberToDisplay(nextUnmatchedRows);
         // Report the row
         LOG.warn( ""  + unmatchedRows +  " unmatched rows are found: "  + rowText);
       }
       return  null ;
     }

2.表的字段类型必须都是string,否则会报错,如果需要别的字段,可以在select中使用cast做转换

1
2
3
4
5
6
7
     for  int  c =  0 ; c < numColumns ; c++) {
       if  (!columnTypes.get(c).equals( TypeInfoFactory.stringTypeInfo)) {
         throw  new  SerDeException(getClass().getName()
             " only accepts string columns, but column["  + c +  "] named "
             + columnNames.get(c) +  " has type "  + columnTypes.get(c));
       }
     }


本文转自菜菜光 51CTO博客,原文链接:http://blog.51cto.com/caiguangguang/1532987,如需转载请自行联系原作者
相关文章
|
SQL Java 数据库
|
SQL 分布式计算 自然语言处理
|
6月前
|
SQL 数据采集 数据挖掘
大数据行业应用之Hive数据分析航班线路相关的各项指标
大数据行业应用之Hive数据分析航班线路相关的各项指标
191 1
|
6月前
|
SQL 存储 大数据
【大数据技术Hadoop+Spark】Hive基础SQL语法DDL、DML、DQL讲解及演示(附SQL语句)
【大数据技术Hadoop+Spark】Hive基础SQL语法DDL、DML、DQL讲解及演示(附SQL语句)
254 0
|
SQL 存储 大数据
黑马程序员-大数据入门到实战-分布式SQL计算 Hive 语法与概念
黑马程序员-大数据入门到实战-分布式SQL计算 Hive 语法与概念
142 0
|
6月前
|
SQL 分布式计算 数据库
【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)
【大数据技术Spark】Spark SQL操作Dataframe、读写MySQL、Hive数据库实战(附源码)
253 0
|
6月前
|
SQL 存储 分布式计算
【大数据技术Hadoop+Spark】Hive数据仓库架构、优缺点、数据模型介绍(图文解释 超详细)
【大数据技术Hadoop+Spark】Hive数据仓库架构、优缺点、数据模型介绍(图文解释 超详细)
1078 0
|
1月前
|
SQL 分布式计算 Java
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
大数据-96 Spark 集群 SparkSQL Scala编写SQL操作SparkSQL的数据源:JSON、CSV、JDBC、Hive
36 0
|
4月前
|
SQL 分布式计算 大数据
大数据处理平台Hive详解
【7月更文挑战第15天】Hive作为基于Hadoop的数据仓库工具,在大数据处理和分析领域发挥着重要作用。通过提供类SQL的查询语言,Hive降低了数据处理的门槛,使得具有SQL背景的开发者可以轻松地处理大规模数据。然而,Hive也存在查询延迟高、表达能力有限等缺点,需要在实际应用中根据具体场景和需求进行选择和优化。
下一篇
无影云桌面