hive 에서 정규 표현 식 을 잘못 사용 하여 운행 이 매우 느 립 니 다.

7014 단어 hive.
업무 보장 부 에 한 가지 수요 가 있 습 니 다. 하 이브 리드 로 한 시간의 데 이 터 를 실시 간 으로 계산 해 야 합 니 다. 예 를 들 어 지금 은 12 시 입 니 다. 저 는 11 시의 데 이 터 를 계산 해 야 합 니 다. 그리고 반드시 1 시간 후에 운행 해 야 합 니 다. 그러나 그들 이 하 이브 리드 로 실 현 했 을 때 하나의 맵 임무 운행 이 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 ] 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 은 매우 간단 합 니 다. 데이터 가 한 열 밖 에 없 는 표 odswls_wap_base_orig 에서 데 이 터 를 가 져 온 다음 각 줄 의 데 이 터 를 split 또는 정규 표현 식 과 일치 시 켜 필요 한 필드 정 보 를 얻 고 마지막 으로 출력 된 데 이 터 를 통 해 weibo 를 만 듭 니 다.mobile_nginx 시계.
그 중 표 odswls_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);
    }

  }

자바 코드 도 사실 간단 합 니 다. 여 기 는 말 이 많 지 않 습 니 다. 포장 제출 job 결과 map 가 가장 느리게 40 분 실 행 했 습 니 다. 평균 map 운행 시간 은 30 분 에 달 했 습 니 다. 전체 job 가 1 시간 안에 완성 되 었 지만 느 렸 습 니 다. 이 문 제 는 자바 로 고 쳐 쓰 면 좋 은 문제 가 아 닌 것 같 습 니 다.
3. 마지막 으로 정규 표현 식 검출
자바 로 바 꾼 maprediuce 의 운행 도 느 린 것 같 습 니 다. 문 제 는 다른 원인 인 것 같 습 니 다. 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 로 바 꾸 었 습 니 다.
자바 코드 의 정규 표현 식 도 수정 되 었 습 니 다.
Pattern p_per_client = Pattern
      .compile("&ua=[^_]*__[^_]*__([^_]*)__([^_]*)__");
  Pattern net_type_parent = Pattern.compile("&networktype=([^&%]*).");
각각 테스트 를 제출 했 습 니 다. 속도 ss 의, 수 정 된 hql 과 Mapreduce 의 전체 작업 은 6 분 동안 실 행 됩 니 다. 평균 map 운행 시간 은 2 분 이 고 속도 가 크게 향상 되 어 그들의 속도 요 구 를 만족 시 켰 습 니 다.
요약:
1. 정규 표현 식 의 맨 앞 에는 '. *' 가 포함 되 어 있 습 니 다. 일치 할 때 첫 번 째 문자 부터 일치 해 야 합 니 다. 속도 가 매우 느 립 니 다. 만약 에 우리 가 일치 하 는 목표 가 명확 한 상황 에서 '. *' 를 제거 해 야 합 니 다.
2. 앞으로 이런 문제 에 부 딪 혔 을 때 정규 표현 식 에 문제 가 있 는 지 꼭 보고 기억 하 세 요.

좋은 웹페이지 즐겨찾기