业务保障部有一个需求,须要用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 =[^ _ ]* __([^ _ ]*)__([^ _ ]*)__([^ _ ]*)__<span style="font-family: Arial, Helvetica, sans-serif;">[^&]*</span>’,
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 ] idc
FROM
ods_wls_wap_base_orig
WHERE
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<LongWritable, Text, Text, Text> {

  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、以后遇到这样的问题的时候。一定要看看正則表達式是不是写得有问题,切记切记。

hive中使用正則表達式不当导致执行奇慢无比的更多相关文章

  1. C++ Tr1中的正則表達式

    要使用正則表達式,首先要有类库支持,C++曾经不像Java或者C#有完整的类库使用,可是在Tr1中早已提供了正则库,仅仅是非常少被人们注意罢了 TR1中包括了一个正则库,来自Boost的 regex, ...

  2. javascript中的正則表達式

    对文本数据进行操作是JavaScript中常见的任务.正則表達式通过同意程序猿指定字符串匹配的模式来简化诸如验证表单中输入是否具有正确格式之类的任务. 1.正則表達式标记: 字符 含义 举例 i 大写 ...

  3. vim中使用正則表達式

    一.使用正則表達式的命令 使用正則表達式的命令最常见的就是 / (搜索)命令. 其格式例如以下: /正則表達式 还有一个非常实用的命令就是 :s(替换)命令,将第一个//之间的正則表達式替换成第二个/ ...

  4. 对于C11中的正則表達式的使用

    Regular Expression Special Characters "."---Any single character(a "wildcard") & ...

  5. hive正則表達式

    hive中实现正則表達式,与java中的正則表達式有所差别: 这里经过探索总结了一些: hive中的正则能够用,可是有所差别,差别在于原来的'\' 转义,这里变成了双斜杠了'\\' hive中的正则解 ...

  6. C++11中正則表達式測试

    VC++2010已经支持regex了, 能够用来编译下述代码. #include <string> #include <regex> #include <iostream ...

  7. JAVA中正則表達式总结

    昨天,我的朋友请教我正則表達式.我也好久没有写过正則表達式了,昨天刚好看了下如鹏网创始人杨中科老师关于正則表達式的解说.使我加深了正則表達式的印像.现我把他总结下: 很多语言,包含Perl.PHP.P ...

  8. JAVA中正則表達式总结(具体解释及用途)

    很多语言,包含Perl.PHP.Python.JavaScript和JScript,都支持用正則表達式处理文本,一些文本编辑器用正則表達式实现高级"搜索-替换"功能.所以JAVA语 ...

  9. python使用正則表達式

    python中使用正則表達式 1. 匹配字符 正則表達式中的元字符有 .  ^  $ *   +  ?  { }  [ ]  \  | ( ) 匹配字符用的模式有 \d 匹配随意数字 \D 匹配随意非 ...

随机推荐

  1. 阿里云服务器基本搭建_错误1_Permission denied (publickey)

    首先 修改这两个密码 然后重启服务器就可以了

  2. Android反编译初步

    网上关于Android反编译的帖子很多,反编译的步骤也是很详细,本文Android反编译参考博客:https://www.cnblogs.com/dhcn/p/7120891.html 而反编译中最主 ...

  3. selenium+python自动化unittest之跳过用例skip

    前言 当测试用例写完后,有些模块有改动时候,会影响到部分用例的执行,这个时候我们希望暂时跳过这些用例. 或者前面某个功能运行失败了,后面的几个用例是依赖于这个功能的用例,如果第一步就失败了,后面的用例 ...

  4. 记录一次通过命令行方式来使用svn碰到的一系列问题

    由于使用Xcode自带的svn管理碰到很多问题,搞得头昏脑胀,找资料时看到小码哥这方面的视频,看完就开始折腾了. 准备:1.远程仓库地址及授权账号(用户名和密码) 2.一份项目代码,之所以要有这份代码 ...

  5. get data from splunk

    link: http://dev.splunk.com/view/python-sdk/SP-CAAAER5 download SDK & setup with python code: im ...

  6. BZOJ 3996 线性代数 最小割

    题意: 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D 分析: 这道题比较绕,我们需要看清题目中那个式子的本 ...

  7. 笔试算法题(38):并查集(Union-Find Sets)

    议题:并查集(Union-Find Sets) 分析: 一种树型数据结构,用于处理不相交集合(Disjoint Sets)的合并以及查询:一开始让所有元素独立成树,也就是只有根节点的树:然后根据需要将 ...

  8. linux性能优化cpu-01性能指标

    学习性能优化的第一步,一定要了解性能指标. 性能指标是什么? 当我们看到性能指标时一定先想到“高并发”.“响应快”,这个两个指标也对应着性能优化的两个核心指标—— “吞吐率”和“低延迟”. 这两个指标 ...

  9. node assert.equal()

    浅测试,使用等于比较运算符(==)来比较 actual 和 expected 参数. const assert = require('assert'); assert.equal(1, 1); // ...

  10. 图解使用IDEA创建第一个Java程序HelloWorld

    前几次给大家分享了怎么在自己的电脑上配置 java 环境,准备工作做好了,我们就要开始我们真正的编码学习了.下面介绍使用 IDEA 创建我们的第一个 HelloWorld 程序. 1.打开 IDEA, ...