博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于hive RegexSerDe的源码分析
阅读量:7193 次
发布时间:2019-06-29

本文共 3236 字,大约阅读时间需要 10 分钟。

  最近有个业务建表使用了 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,如需转载请自行联系原作者
你可能感兴趣的文章
潇洒人生“二十贵”
查看>>
poj1269
查看>>
压缩、解压缩流GZipStream
查看>>
js编程思路--把相同功能的代码,配置放到一个对象里
查看>>
Oracle性能优化
查看>>
拖动缩放[转]
查看>>
ASP.NET MVC---自定义HtmlHelper方法
查看>>
javaweb入门(4)-- 详细了解http协议2
查看>>
POJ-3686 The Windy's 犀利构图+KM
查看>>
重新认识c++的cin、cout
查看>>
poj1611
查看>>
多例设计模式与枚举
查看>>
【转】Scrum角色及其职责介绍
查看>>
【动画】【特效】activity跳转华丽的过渡效果(转载)
查看>>
使用Eclipse进行远程调试【转】
查看>>
闲谈简单设计(KISS)疑惑
查看>>
四、Html5 语音识别
查看>>
<![CDATA[ ]]> 是什么东东
查看>>
Logger 源码解析 --- MyLogger
查看>>
设置VMware随系统开机自动启动并引导虚拟机操作系统
查看>>