使用regex在Apache Hive中创建表将返回所有NULL值

时间:2016-12-18 12:26:18

标签: regex hadoop hive

我有很多日志文件* .log,我想用以下语法导入Hive表:

CREATE EXTERNAL TABLE cache_22 ( 
a STRING, 
b STRING, 
c STRING, 
d STRING, 
e STRING, 
f STRING,
g STRING,
h  STRING, 
i STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe' 
WITH SERDEPROPERTIES ( 'input.regex' =  '(\d+\w+\d+)\:.*?\[.*?\]\s(\d+\.\d+)\s(\d+\.\d+)\s\w*\s\d*\s(\d*)\s\d\s\w*\s(((?:[0-9]{1,3}\.){3}[0-9]{1,3}))\s(((?:[0-9]{1,3}\.){3}[0-9]{1,3}))\:\d*\s(?:-|http:\/\/|www\.|https:\/\/)([^\/]+)','output.format.string' = "%1$$s %2$$s %3$$s %4$$s %5$$s %6$$s %7$$s %8$$s %9$$s")';

但是当我查询它时会带来如下的空值:

NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

这是我的日志样本:

25Oct2016:103130.123456 [1234567a3] 0.522550 1.244476 TCP_PARTIAL_HIT 206 65871 0 GET 10.10.10.199 11.11.11.11:80 
25Oct2016:103130.654321 [1234567e8] 0.144449 0.178851 TCP_MISS 200 7035 0 GET 5.5.5.5 10.20.30.40:80 http://stackoverflow.com/questions/23668713/getting-null-values-in-hive-create-load-query-with-regex

请纠正我的错误。

感谢。

1 个答案:

答案 0 :(得分:0)

在您的情况下,正则表达式(\\s(?:-|http:\\/\\/|www\\.|https:\\/\\/)([^\\/]+))似乎与您正在使用的serde有关。您正在使用的serde似乎无法编译正则表达式的那些部分,因此它限制了获取数据。

我尝试了多种方案,结果如下。

场景1:没有对Data和regEx进行任何修改

输入数据

[user1@server1 ~]$ hdfs dfs -cat /user/user1/hive_poc/hive3/file1.txt
25Oct2016:103130.123456 [1234567a3] 0.522550 1.244476 TCP_PARTIAL_HIT 206 65871 0 GET 10.10.10.199 11.11.11.11:80
25Oct2016:103130.654321 [1234567e8] 0.144449 0.178851 TCP_MISS 200 7035 0 GET 5.5.5.5 10.20.30.40:80 http://stackoverflow.com/questions/23668713/getting-null-values-in-hive-create-load-query-with-regex
[user1@server1 ~]$

Hive创建表语句

hive> CREATE EXTERNAL TABLE tbl_regex_test3 (
    > a STRING,
    > b STRING,
    > c STRING,
    > d STRING,
    > e STRING,
    > f STRING,
    > g STRING,
    > h STRING,
    > i STRING
    > )
    > ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
    > WITH SERDEPROPERTIES ( 'input.regex' =  '(\\d+\\w+\\d+)\\:.*?\\[.*?\\]\\s(\\d+\\.\\d+)\\s(\\d+\\.\\d+)\\s\\w*\\s\\d*\\s(\\d*)\\s\\d\\s\\w*\\s(((?:[0-9]{1,3}\\.){3}[0-9]{1,3}))\\s(((?:[0-9]{1,3}\\.){3}[0-9]{1,3}))\\:\\d*\\s(?:-|http:\\/\\/|www\\.|https:\\/\\/)([^\\/]+)',
    > 'output.format.string' = "%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s")
    > LOCATION '/user/user1/hive_poc/hive3/';
OK
Time taken: 0.046 seconds
hive>

结果:没有获得任何数据。

hive> set hive.cli.print.header=true;
hive> add jar /home/user1/hive-contrib-0.10.0-cdh4.2.0.jar;
Added [/home/user1/hive-contrib-0.10.0-cdh4.2.0.jar] to class path
Added resources: [/home/user1/hive-contrib-0.10.0-cdh4.2.0.jar]
hive> select * from tbl_regex_test3;
OK
tbl_regex_test3.a       tbl_regex_test3.b       tbl_regex_test3.c       tbl_regex_test3.d       tbl_regex_test3.e       tbl_regex_test3.f       tbl_regex_test3.g    tbl_regex_test3.h        tbl_regex_test3.i
NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
Time taken: 0.047 seconds, Fetched: 2 row(s)
hive>

场景2:仅删除了错误的regEx。

输入数据

[user1@server1 ~]$ hdfs dfs -cat /user/user1/hive_poc/hive/file1.txt
25Oct2016:103130.123456 [1234567a3] 0.522550 1.244476 TCP_PARTIAL_HIT 206 65871 0 GET 10.10.10.199 11.11.11.11:80
25Oct2016:103130.654321 [1234567e8] 0.144449 0.178851 TCP_MISS 200 7035 0 GET 5.5.5.5 10.20.30.40:80 http://stackoverflow.com/questions/23668713/getting-null-values-in-hive-create-load-query-with-regex
[user1@server1 ~]$

Hive创建表语句

hive> CREATE EXTERNAL TABLE tbl_regex_test2 (
    > a STRING,
    > b STRING,
    > c STRING,
    > d STRING,
    > e STRING,
    > f STRING,
    > g STRING,
    > h STRING,
    > i STRING
    > )
    > ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
    > WITH SERDEPROPERTIES ( 'input.regex' =  '(\\d+\\w+\\d+)\\:.*?\\[.*?\\]\\s(\\d+\\.\\d+)\\s(\\d+\\.\\d+)\\s\\w*\\s\\d*\\s(\\d*)\\s\\d\\s\\w*\\s(((?:[0-9]{1,3}\\.){3}[0-9]{1,3}))\\s(((?:[0-9]{1,3}\\.){3}[0-9]{1,3}))\\:\\d*',
    > 'output.format.string' = "%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s")
    > LOCATION '/user/user1/hive_poc/hive';
OK
Time taken: 0.134 seconds

结果:仅从第1行获取数据,第2行为空,因为它与输入regEx不匹配。

hive> set hive.cli.print.header=true;
hive> add jar /home/user1/hive-contrib-0.10.0-cdh4.2.0.jar;
Added [/home/user1/hive-contrib-0.10.0-cdh4.2.0.jar] to class path
Added resources: [/home/user1/hive-contrib-0.10.0-cdh4.2.0.jar]
hive> select * from tbl_regex_test2;
OK
tbl_regex_test2.a       tbl_regex_test2.b       tbl_regex_test2.c       tbl_regex_test2.d       tbl_regex_test2.e       tbl_regex_test2.f       tbl_regex_test2.g    tbl_regex_test2.h        tbl_regex_test2.i
25Oct2016       0.522550        1.244476        65871   10.10.10.199    10.10.10.199    11.11.11.11     11.11.11.11     NULL
NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
Time taken: 0.046 seconds, Fetched: 2 row(s)
hive>

场景3:从数据中删除了网址部分并删除了错误的regEx。

输入数据

[user1@server1 ~]$ hdfs dfs -cat /user/user1/hive_poc/hive1/file.log
25Oct2016:103130.123456 [1234567a3] 0.522550 1.244476 TCP_PARTIAL_HIT 206 65871 0 GET 10.10.10.199 11.11.11.11:80
25Oct2016:103130.654321 [1234567e8] 0.144449 0.178851 TCP_MISS 200 7035 0 GET 5.5.5.5 10.20.30.40:80
[user1@server1 ~]$

Hive创建表语句

hive> CREATE EXTERNAL TABLE tbl_regex_test1 (
    > a STRING,
    > b STRING,
    > c STRING,
    > d STRING,
    > e STRING,
    > f STRING,
    > g STRING,
    > h STRING,
    > i STRING
    > )
    > ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
    > WITH SERDEPROPERTIES ( 'input.regex' =  '(\\d+\\w+\\d+)\\:.*?\\[.*?\\]\\s(\\d+\\.\\d+)\\s(\\d+\\.\\d+)\\s\\w*\\s\\d*\\s(\\d*)\\s\\d\\s\\w*\\s(((?:[0-9]{1,3}\\.){3}[0-9]{1,3}))\\s(((?:[0-9]{1,3}\\.){3}[0-9]{1,3}))\\:\\d*',
    > 'output.format.string' = "%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s")
    > LOCATION '/user/user1/hive_poc/hive1';
OK
Time taken: 0.15 seconds
hive>

结果:太棒了!!从两行获取记录。

hive> set hive.cli.print.header=true;
hive> add jar /home/user1/hive-contrib-0.10.0-cdh4.2.0.jar;
Added [/home/user1/hive-contrib-0.10.0-cdh4.2.0.jar] to class path
Added resources: [/home/user1/hive-contrib-0.10.0-cdh4.2.0.jar]
hive> select * from tbl_regex_test1;
OK
tbl_regex_test1.a       tbl_regex_test1.b       tbl_regex_test1.c       tbl_regex_test1.d       tbl_regex_test1.e       tbl_regex_test1.f       tbl_regex_test1.g    tbl_regex_test1.h        tbl_regex_test1.i
25Oct2016       0.522550        1.244476        65871   10.10.10.199    10.10.10.199    11.11.11.11     11.11.11.11     NULL
25Oct2016       0.144449        0.178851        7035    5.5.5.5 5.5.5.5 10.20.30.40     10.20.30.40     NULL
Time taken: 0.057 seconds, Fetched: 2 row(s)
hive>

从上面的结果我得出的结论是,您使用的regEx无法获取URL或者它与此Hive serde不兼容。

当我使用online regular expression compiler验证regEx并从第2行获得结果时,我再次感到惊讶。请参阅下面的图片以获得更多说明

enter image description here

结果如下: enter image description here

从上面的结果来看,我是悬而未决,认为这是一个serde问题或正则表达问题,并且还会等待其他一些答案。

另一方面,我们应该避免在hive中使用正则表达式技术,因为它与数据的位置紧密耦合,并且可以在输入数据的微小变化时中断。