728x90

udemy - hadoop 기초강의를 보면서 정리한 내용입니다

 

세 번째 섹션에서는 Apache Pig에 대한 대략적인 설명으로 이루어졌다. 


 Apache Pig

이전 섹션에서 공부한 맵리듀스는 Hadoop의 가장 오래된 데이터 처리 기술이고 가장 어렵기도 하다.
이러한 맵리듀스의 어려움을 조금 해결하기 위해 나온 것이 Apache Pig이며, Pig를 사용해 더 쉽게 데이터를 처리할 수 있다

이는 Pig Latin이라는 스크립팅 언어이고 Hadoop과 MapReduce 위에 구축되었다.
이를 통해 매퍼와 리듀서를 작성하지 않고
MapReduce 작업을 할 수 있는 것이다.

 

MapReduce의 한계

지난 섹션에서는 MapReduce가 어떻게 작동하는지 살펴봤다
Python을 사용하며 STREAMING을 사용해 많은 것들을 단순화시켰음에도 불구하고 MapReduce 작업을 위해 많은 양의 코딩과 디버깅으로 매퍼와 리듀서의 개념에 모든 것을 짜 맞춰야 했다.
그리고 주어진 어떤 사업적인 분석 문제를
매퍼와 리듀서의 프레임에 맞추어 재해석하는 것이 쉽지만은 않다

MapReduce의 가장 큰 문제는 개발 사이클 타임이다.
MapReduce 프로그램을 개발해 실행하고 원하는 작업을 수행하기까지 오랜 시간이 걸린다.

그래서 Pig가 등장한 것이다.

 

Apache Pig의 장점

1. 사용성이 좋다

Pig는 MapReduce 위에서 작동하고 Pig Latin이라는 새 프로그래밍 언어를 사용한다. 이는 SQL과 비슷하다.

다른 점은 Pig는 절차형 언어라는 것이다. 아주 간단한 스크립트 양식을 사용해 단계별로 데이터 간에 여러 관계를 설정한다.
그리고나서 SQL과 비슷한 작업을 한다.
즉 데이터를 선택하고 필터하고 한 줄씩 변형한다

내부적으로는 결국 MapReduce로 번역이 되지만 외부적으로 사용자가 사용할 때는 맵리듀스에 대해 고려하지 않고 사용할 수 있다.

Pig가 MapReduce 위에 구축되었고 Pig Latin를 사용해 데이터를 분석하는 스크립트를 아주 간단하게 작성할 수 있다.

스크립트는 MapReduce로 번역이 되고 매퍼와 리듀서는 YARN 위에서 돌아가며 HDFS의 데이터를 액세스한다

즉 SQL과 비슷한 언어로 작성되고 좀 더 사용성이 좋게 사용되지만, 이렇게 작성된 언어가 내부적으로 MapReduce로 해석되어서 데이터를 다룬다.

2. 빠른 속도

그리고 생각보다 속도도 빠르다. Pig는 MapReduce 외에도 TEZ를 사용할 수 있는데, TEZ는 MapReduce보다도 훨씬 빠르기 때문에 Pig를 TEZ와 함께 사용함으로써 속도적인 면에서도 더 이득이다.

강의 후반부에 TEZ를 더 자세히 다루겠지만 기본적으로 TEZ는 작업(job)을 훨씬 효율적으로 체계화는 방식을 갖고 있으며 이를 '방향성 비사이클 그래프'라고 부른다.
TEZ는 맵리듀스의 작동 방식 내에서 매퍼와 리듀서, 그리고 데이터 출력 작업 간의 상호 의존성을 파악하고 의도한 바를 이루기 위한 가장 효율적인 경로를 계산한다.

TEZ를 사용할 때 MapReduce보다 대략 10배 정도는 빨랐다

3. Pig Latin의 확장성

Pig Latin의 사용이 제한적인가에 대한 우려에 대해서도 Pig Latin은 굉장히 확장성이 크기 때문에 '사용자 정의 함수'(UDF)를 사용해 하고자 하는 거의 모든 일을 할 수 있다

커스텀 함수를 사용해 Pig Latin에 연결하고 필요하다면 독립적인 매퍼와 리듀서를 사용할 수 있다.
즉 Pig와 MapReduce의 혼합해서 사용할 수 있는 것이다.

4. Hadoop에 종속되지 않음

또한 Pig를 Hadoop 클러스터나 종속된 기술을 사용하지 않고도 독립적으로 간단한 작업을 수행할 수 있다.
스크립트를 MapReduce로 번역할 수도 있고
그보다 더 빠른 TEZ로 번역해 사용할 수도 있다

결국 다 똑같은 Pig Latin 스크립트이지만 내부적으로는 아주 정교하게 설계되어 최대한 효율적으로 전체 클러스터에 걸쳐 작업을 수행할 수 있다

 

Pig를 사용하는 방법

Pig를 사용할 수 있는 몇 가지 방법이 있다.

1. 명령줄 해석 프로그램 Grunt를 사용

마스터 노드에서 'pig'라고 입력하면 Grunt 프롬프트가 나오고 Pig 스크립트를 한 줄씩 작성하고 실행할 수 있다
만약 작은 데이터 세트를 가지고 있고 Pig를 통해 작은 실험을 하고 있다면 좋은 수단이다

2. 스크립트를 파일에 저장하고 명령줄에서 Pig를 사용해 실행

이 말은 Crontab 등에서 주기적으로 실행할 수도 있다는 뜻이다.

3. Ambari(hadoop echo system을 위한 웹UI제공)를 사용

Ambari에는 Pig 화면이 구성되어 있고 스크립트 작성, 실행, 저장 등의 작업을 웹 브라우저에서 할 수 있다.

 

Apache Pig 예시

1. 영화 평점 데이터를 불러오기

 

불러오려는 데이터의 각 줄은 사용자 ID, 영화 ID, 평점과 타임스탬프가 있다
한 줄의 코드로 그 데이터를 Pig의 '관계성'(relation) 속으로 불러올 수 있다

'ratings'라는 관계성을 만들고 이걸 데이터 세트라고 생각할 것이다.
'ratings' 관계성은 'LOAD' 함수를 사용해 디스크에서 데이터를 불러온다.

다음은 HDFS로의 경로이다.
'user/maria_dev/ml-100k/u.data'이고 HDFS 클러스터 내의 위치이다.

 'AS' 절은 스키마를 부여한다.

Pig와 관계형 데이터베이스의 차이점은 데이터를 불러올 때 스키마가 적용되는지이다.
Pig에는 연관돼있는 내재된 구조나 스키마 혹은 유형이 없다

여기에 보이는 것처럼 텍스트 데이터를 불러와서 'AS'를 사용해 각 필드에 이름과 유형을 부여할 수 있다

이를 통해 'ratings' 관계성과 그 스키마가 구성됐으며 각 줄에 정보의 '투플'(tuple)을 가진 관계성을 돌려받았다

2. 영화 정보 데이터 불러오기

이제는 'u.item' 파일을 가져와야 한다. 거기에 영화 ID와 제목 간의 매핑되어 있기 때문이다.

해당 데이터는 데이터 분리 기호로 탭 대신에 막대기('|')를 사용한다.

전과 동일하게 'LOAD' 명령어를 사용하고 'metadata'라는 관계성을 만들어 데이터를 영화 ID와 연관 짓는다.
HDFS에 다운로드한 'u.item' 파일의 경로를 특정하고
'PigStorage'를 막대기 문자와 사용한다.

이것은 탭이 아닌 막대기로 구분된 필드 기반 양식을 사용하겠다는 의미이다.

이전처럼 'AS'를 사용해 분명한 스키마를 암시하고 데이터가 들어오면 이 틀에 맞춘다.

이 'DUMP' 명령어는 Pig 스크립트를 개발할 때 굉장히 유용하다.
이는 이 관계성 안에 뭐가 있는지 볼 수 있게 해 주므로 디버깅 등에 굉장히 유용하고 내가 생각한 대로 데이터가 추출되는지 확인할 수 있다

3. 영화 정보 데이터 정렬

다음으로 데이터들을 우리가 사용할 수 있게 변환해야 한다.
이번 예시에서는 개봉일을 기준으로 정렬하고자 한다.

'metadata'를 불러온 이후에 사용되는 'FOREACH'와 'GENERATE' 명령어를 살펴보자
이 줄은 'nameLookup'이라는 새로운 관계성을 기존의 관계성으로부터 생성한다.
'metadata'의 각 줄을 가져와 다음을 포함하는 'nameLookup'이라는 관계성의 새로운 행을 생성한다.

기존 관계성에서 가져온 영화 ID, 영화 제목, 그리고 이 날짜 시간 함수를 사용해 'dd-MMM-yyyy' 양식의 개봉일을, 유닉스 타임스탬프로 변환한다.

이 새 열을 'AS' 명령어를 사용해 'releaseTime'이라고 명명한다.

이제 'nameLookup'이라는 새 관계성이 생겼고 이 안에는 영화 ID 열, 영화 제목 열, 그리고 개봉일 열이 있다

4. 영화 평점 데이터 가공하기(group by)

다음으로 해야 할 일은 각각의 영화와 관련된 평점을 찾아내야 한다. 각 영화의 평균 평점을 구해야 하기 때문이다.
 'GROUP BY'를 사용해 영화 ID 별로 평점을 모을 것이다.

 

해당 작업은 리듀싱 작업이랑 비슷하다. 영화 ID에 리듀싱을 해서 각 영화별로 관련된 평점 값을 집계하는 것이다.

5. 영화 평점 평균 구하기

 

 6. 기타 작업(filter ,  join, order by)

-> 평균 평점이 5점이상인 영화 찾기

-> 평점와 영화ID를 볼수있는 데이터에서 이름도 알수있도록 평점 데이터와 영화정보 데이터를 join하기

-> 개봉일 기준으로 정렬하기

 

Pig(Latin) 주요 명령어들

위의 예시에서 다뤄본 Pig Script언어 포함 주요 명령어에 대해서 정리해보려한다. 

 
 
- 'LOAD'는 데이터를 관계성으로 불러온다.

- 'STORE'는 디스크에 데이터를 기록한다.

즉 'LOAD'는 읽고 'STORE'는 기록한다.

예를들어 STORE 관계성 이름 INTO 파일 이름으로 사용된다.

그리고 탭 이외의 구분 기호를 사용하고 싶다면 'USING PigStorage(':');' 이런 식으로 작성한다.
JSON이나 Parquet 같은
다른 저장소 클래스도 사용할 수 있다.

실제 작업 환경에서는 작업 결과를 'DUMP'를 사용해 콘솔에 출력하기보다는 파일에 기록해야 할 경우가 많다.

- 'FILTER'

- 'DISTINCT'는 관계성 내의 고유한 값을 가져온다

- 'FOREACH/GENERATE'를 사용해 기존 관계성의 데이터를 한 줄씩 가져와 변형해 새 관계성을 생성한다.

- 'MAPREDUCE'는 관계성에 명시적인 매퍼와 리듀서를 호출할 수 있다

- 'STREAM'도 확장성에 관한 것이다. Pig의 결과물을 어떤 처리 장치로 표준 입출력을 사용해 스트리밍 할 수 있다.

- 'SAMPLE'은 관계성 내에 무작위의 표본을 만든다. 'SAMPLE'을 'JOIN'과 함께 사용할 때는 주의해야 한다.
무작위의 표본으로 구성된 관계성이 잘 합쳐지지 않을 수 있다.

- 'JOIN'

- 'COGROUP'은 'JOIN'의 변형. 'JOIN'에서는 합쳐진 행을 단일 투플에 넣는다면 'COGROUP'은 키별로 서로 다른 투플에 넣어 계층적 구조를 생성한다. 'JOIN'보다 조금 더 구체적이다. 'COGROUP'은 확실히 더 구조화된 데이터를 만든다.

- 'GROUP'은 주어진 키와 관련된 값들을 빨아들여 그룹을 생성한다.

- 'CROSS'는 두 관계성 사이에서 모든 조합을 한다.
한 카탈로그의 제품을 다른 카탈로그의 모든 제품과 비교 분석할 때 'CROSS'를 사용해 제품들의 모든 조합을 가진 더 큰 매트릭스를 만들 수 있다

- 'CUBE'는 두 개 이상의 열을 가져와 모든 조합을 만들 수 있다

- 'ORDER'는 관계성을 정렬할 때 사용

- 'RANK'는 'ORDER'와 비슷하지만 정렬하는 대신 각 행에 등번호를 부여한다. 순서를 바꾸진 않지만 각 행에 번호를 부여하는 것.

- 'LIMIT'은 특히 디버깅할 때 유용. 관계성에서 처음부터 정해진 만큼의 결과만을 가져온다.

- 'UNION'은 두 개의 관계성을 가져와 합친다

- 'SPLIT'은 하나 이상의 관계성으로 나눈다

- 'DESCRIBE'는 주어진 관계성의 스키마를 보여준다. Pig가 그 관계성을 어떻게 보는지 내부의 이름과 유형을 보여준다.

- 'EXPLAIN'은 SQL의 'EXPLAIN PLAN'과 비슷하다. Pig가 주어진 쿼리를 어떻게 실행할지에 관한 계획을 볼 수 있다.

- 'ILLUSTRATE'는 관계성에서 표본을 가져와 각 데이터 조각들을 가지고 무얼 하는지 보여준다.

Pig 내부에서 무슨 일이 일어나는지 더 자세히 알고 싶다면 'EXPLAIN'과 'ILLUSTRATE'를 사용하면 되고 'DESCRIBE'는 관계성의 스키마를 보여준다.

- AVG는 평균을 구한다.

- 'CONCAT'

- 'COUNT'

- 'MAX'는 최댓값을, 'MIN'은 최솟값을 'SIZE', 'SUM'은 다 더하는 것.

사용자 정의 함수(UDF)

이곳에선 Java 코딩을 하고 jar 파일을 만드는 등의 작업을 한다. 이 함수들은 사용자 정의 함수를 관리하는데 사용한다.

- 'REGISTER'는 UDF가 포함된 jar 파일을 가져오는데 사용

- 'DEFINE'은 그 함수에 이름을 부여해 Pig 스크립트 내에서 사용할 수 있게 한다.

- 'IMPORT'는 Pig 파일의 매크로를 불러오는데 사용. 그러니까 재사용 가능한 Pig 코드를 매크로로 저장했다면 그 매크로를 다른 Pig 스크립트에 쉽게 불러올 수 있다.

다양한 저장소 클래스

- 대표적으로 'PigStorage'가 있다. 필드 기반의 데이터를 사용하고 입력이든 출력이든 각 행에 구분 기호를 사용한다.

- 'TextLoader'는 비정형데이터를 UTF-8 형식으로 로드한다. 각 결과 튜플에는 한 줄의 입력 텍스트가 있는 단일필드가 포함된다. 한 줄의 BLOB(Binary Large Object)를 가지고 무엇이든 할 수 있다.

- 그리고 더 구조화된 JSON

- Avro를 사용할 수 있다. Avro는 Hadoop에서 자주 쓰이는 일렬화(serialization)나 비일렬화 양식에 특화돼 있다. 스키마를 갖도록 할 수도 있고 Hadoop 클러스터에 걸쳐 나눌 수도 있다

- Parquet는 열(column) 지향 데이터 양식이며 역시 자주 사용

- 'OrcStorage' 역시 자주 사용되는 압축된 양식

- 'HBaseStorage'는 Pig를 SQL의 데이터베이스인 HBase와 결합할 수 있다.

 

참고자료

https://runebook.dev/ko/docs/apache_pig/func#textloader

 

Apache Pig - 내장 함수 - Introduction Pig는 내장 함수 세트 (eval, load / store, math, string, bag 및 tuple 함수)

Pig는 내장 함수 세트 (eval, load / store, math, string, bag 및 tuple 함수)와 함께 제공됩니다. 두 가지 주요 속성은 내장 함수를 사용자 정의 함수 (UDF)와 구분합니다. 첫째, 내장 함수는 Pig가 어디에 있는

runebook.dev

 

728x90

+ Recent posts