博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hive中使用正則表達式不当导致执行奇慢无比
阅读量:5789 次
发布时间:2019-06-18

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

       业务保障部有一个需求,须要用hive实时计算上一小时的数据。比方如今是12点,我须要计算11点的数据,并且必须在1小时之后执行出来。可是他们用hive实现的时候发现就单个map任务执行都超过了1小时,根本没法满足需求,后来打电话让我帮忙优化一下,下面是优化过程:

1、hql语句:

CREATE TABLE weibo_mobile_nginx AS SELECT	split(split(log, '`') [ 0 ], '\\|')[ 0 ] HOST,	split(split(log, '`') [ 0 ], '\\|')[ 1 ] time,	substr(		split(			split(split(log, '`') [ 2 ], '\\?')[ 0 ], ' '		)[ 0 ], 2	)request_type,	split(		split(split(log, '`') [ 2 ], '\\?')[ 0 ], ' '	)[ 1 ] interface,	regexp_extract(		log,		’.*& ua =[^ _ ]* __([^ _ ]*)__([^ _ ]*)__([^ _ ]*)__[^&]*’,		3	)version,	regexp_extract(		log,		’.*& ua =[^ _ ]* __([^ _ ]*)__([^ _ ]*)__([^ _ ]*)__.* ',1) systerm,regexp_extract(log,’.*&networktype=([^&%]*).*',		1	)net_type,	split(log, '`')[ 4 ] STATUS,	split(log, '`')[ 5 ] client_ip,	split(log, '`')[ 6 ] uid,	split(log, '`')[ 8 ] request_time,	split(log, '`')[ 12 ] request_uid,	split(log, '`')[ 13 ] http_host,	split(log, '`')[ 15 ] upstream_response_time,	split(log, '`')[ 16 ] idcFROM	ods_wls_wap_base_origWHERE	dt = '20150311'AND HOUR = '08'AND(	split(log, '`')[ 13 ]= 'api.weibo.cn'	OR split(log, '`')[ 13 ]= 'mapi.weibo.cn’);
事实上这个hql非常easy,从一个仅仅有一列数据的表ods_wls_wap_base_orig中获取数据,然后对每一行数据进行split或者正則表達式匹配得到须要的字段信息。最后通过输出的数据创建weibo_mobile_nginx表。

当中表ods_wls_wap_base_orig的一行数据格式例如以下:

web043.mweibo.yhg.sinanode.com|[11/Mar/2015:00:00:01 +0800]`-`"GET /2/remind/unread_count?v_f=2&c=android&wm=9847_0002&remind_version=0&with_settings=1&unread_message=1&from=1051195010&lang=zh_CN&skin=default&with_page_group=1&i=4acbdd0&s=6b2cd11c&gsid=4uQ15a2b3&ext_all=0&idc=&ua=OPPO-R8007__weibo__5.1.1__android__android4.3&oldwm=9893_0028 HTTP/1.1"`"R8007_4.3_weibo_5.1.1_android"`200`[121.60.78.23]`3226234350`"-"`0.063`351`-`121.60.78.23`1002792675011956002`api.weibo.cn`-`0.063`yhg 20150311    00

仅仅有1列,列名是log。

2、既然hql实现非常慢,我第一次优化的尝试就是写mapreduce

map代码例如以下:

public class Map extends Mapper
{ private Text outputKey = new Text(); private Text outputValue = new Text(); Pattern p_per_client = Pattern .compile(".*&ua=[^_]*__([^_]*)__([^_]*)__([^_]*)__[^&]*"); Pattern net_type_parent = Pattern.compile(".*&networktype=([^&%]*).*"); public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String[] arr = value.toString().split("`"); if (arr[13].equals("api.weibo.cn") || arr[13].equals("mapi.weibo.cn")) { Matcher matcher = p_per_client.matcher(value.toString()); String host = ""; String time = ""; String request_type = ""; String interface_url = ""; String version = ""; String systerm = ""; String net_type = ""; String status = ""; String client_ip = ""; String uid = ""; String request_time = "0"; String request_uid = ""; String http_host = ""; String upstream_response_time = "0"; String idc = ""; host = arr[0].split("\\|")[0]; time = arr[0].split("\\|")[1]; request_type = arr[2].split("\\?")[0].split(" ")[0].substring(1); interface_url = arr[2].split("\\?")[0].split(" ")[1]; if (matcher.find()) { version = matcher.group(1); systerm = matcher.group(2); } Matcher matcher_net = net_type_parent.matcher(value.toString()); if (matcher_net.find()) { net_type = matcher_net.group(1); } status = arr[4]; client_ip = arr[5]; uid = arr[6]; if (!arr[8].equals("-")) { request_time = arr[8]; } request_uid = arr[12]; http_host = arr[13]; if (!arr[15].equals("-")) { upstream_response_time = arr[15]; } idc = arr[16]; outputKey.set(host + "\t" + time + "\t" + request_type + "\t" + interface_url + "\t" + version + "\t" + systerm + "\t" + net_type + "\t" + status + "\t" + client_ip + "\t" + uid + "\t" + request_uid + "\t" + http_host + "\t" + idc); outputValue.set(request_time + "\t" + upstream_response_time); context.write(outputKey, outputValue); } }

java代码事实上也非常easy,这里不多说。打包提交job。结果map最慢的执行了40分钟。平均map执行时间达到30分钟,尽管整个job在1小时内完毕了。可是也非常慢。这个问题看来不是用java改写就能好的问题。

3、最后检測正則表達式

改用java实现的mapreduce执行也非常慢。看来问题还是其它原因。我看了一下hql中的正則表達式。改动了几个地方:

原来的:

regexp_extract(                log,                ’.*& ua =[^ _ ]* __([^ _ ]*)__([^ _ ]*)__([^ _ ]*)__[^&]*’,                3        )version,        regexp_extract(                log,                ’.*& ua =[^ _ ]* __([^ _ ]*)__([^ _ ]*)__([^ _ ]*)__.* ',1)        systerm,regexp_extract(log,’.*&networktype=([^&%]*).*',                1        )net_type,
改动后:
regexp_extract(		log,		'&ua=[^_]*__[^_]*__([^_]*)__[^_]*__',		1	)version,	regexp_extract(		log,		'&ua=[^_]*__[^_]*__[^_]*__([^_]*)__',		1	)systerm,	regexp_extract(		log,		'&networktype=([^&%]*)',		1	)net_type,
事实上匹配目标非常明白,所以我把正則表達式前后的".*"去掉了。同一时候去掉了不是必需的group。索引都改成了1。

java代码的正則表達式也进行了改动:

Pattern p_per_client = Pattern      .compile("&ua=[^_]*__[^_]*__([^_]*)__([^_]*)__");  Pattern net_type_parent = Pattern.compile("&networktype=([^&%]*).");
分别提交測试了一下,速度ss的。改动后的hql和mapreduce整个作业6分钟执行完毕。平均map执行时间2分钟。速度提升非常大,满足了他们的速度要求。

总结:

1、正則表達式最前面包括“.*”,这样在匹配的时候须要从第一个字符開始匹配。速度很很慢,假设我们匹配的目标很明白的情况下。应该去掉“.*”

2、以后遇到这样的问题的时候。一定要看看正則表達式是不是写得有问题,切记切记。

       

转载于:https://www.cnblogs.com/yutingliuyl/p/7159300.html

你可能感兴趣的文章
原型模式(Prototype )
查看>>
201521123009 《Java程序设计》第1周学习总结
查看>>
年终述职--常见问题分析解答
查看>>
C#_细说Cookie_Json Helper_Cookies封装
查看>>
对事件循环的一点理解
查看>>
在mui中创建aJax来请求数据..并展示在页面上
查看>>
spring 之AOP
查看>>
总结 15/4/23
查看>>
守护进程
查看>>
JavaScript概述
查看>>
linux crontab 实现每秒执行
查看>>
python之元组
查看>>
Windows 7环境下网站性能测试小工具 Apache Bench 和 Webbench使用和下载
查看>>
C#常见错误解决方法
查看>>
安装cnpm (npm淘宝镜像)
查看>>
js 利用事件委托解决mousedown中的click
查看>>
游戏设计艺术 第2版 (Jesse Schell 著)
查看>>
Java 面向对象(基础) 知识点总结I
查看>>
miniUI mini-monthpicker ie8兼容性问题
查看>>
C++11 double转化为string
查看>>