Open chominyeong opened 9 months ago
- 비구조화/스키마리스 데이터 –[Hive]→ 데이터 구조화 및 열지향 스토리지로 저장
- 구조화 데이터 –[Presto]→ 비정규화 테이블로 데이터 마트에 보냄
# Hive 기동
$ hive
# 외부 테이블 'access_los_csv'를 정의
hive> CREATE EXTERNAL TABLE access_log_csv(
> time string, request string, status int, bytes int
> )
> # csv 형식임을 지정
> ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
> # 경로를 지정(디렉토리 내의 모든 파일이 읽혀짐)
> STORED AS TEXTFILE LOCATION '/var/log/access_log/'
> # csv의 헤더행 스킵
> TBLPROPERTIES ('skip.header.line.count'='1');
OK
Time taken: 1.938 seconds
# 상태별로 레코드 수를 센다.
hive> SELECT status, count(*) cnt
> FROM access_log_csv GROUP BY status LIMIT 2; #2개의 행 출력
...
OK
200 1701534
302 46573
Time taken: 8.664 seconds, Fetched: 2 row(s)
데이터 집계의 고속화를 위해, (배치형 쿼리 엔진용)
# ORC 형식의 테이블 'access_log_orc'로 변환 hive> CREATE TABLE access_log_orc STORED AS ORC AS SELECT cast(time AS timestamp) time, request, status, cast(bytes AS bigint) bytes FROM access_log_csv; OK Time taken: 15.993 seconds
hive> SELECT statux, count(*) cnt
FROM access_log_orc GROUP BY status LIMIT 2; ... OK 200 1701534 302 46573 Time taken: 1.567 seconds, Fetched: 2 row(s)
> ORC : Optimized Row Columnar 컬럼 기반으로 데이터 저장=열 지향
- ORC 형식으로 변환할 때에는 시간이 다소 걸리지만, **변환 후 테이블의 집계는 1.5초로 1/10 단축**되었다.
- **열 지향 스토리지로 변환**함으로써 **집계에 시간이 고속화**된다. → **Hive와 같은 배치형 쿼리 엔진에서 적합**
<br><br>
### 2. 비정규화 테이블 만들기
비정규화 테이블 만들기 ├── Hive(배치형 쿼리 엔진) │ ├── 서브 쿼리 안에서 레코드 수를 줄이는 방법 │ └── 데이터의 편향을 방지하는 방법 └── Presto(대화형 쿼리 엔진)
#### Hive와 Presto의 차이
- Hive
- 시간이 걸리는 배치 처리는 Hive를 사용한다.
- 비정규화 테이블이 수억 레코드나 되면, 이것을 데이터 마트에 보내는 것만으로도 상당한 시간이 걸리므로 배치형 시스템을 사용하는 것이 리소스 이용 효율을 높인다.
- Presto
- 작은 쿼리를 여러 번 실행할 때 사용한다.
<br>
### 2-a. Hive로 비정규화 테이블 만들기
#### 👉 서브 쿼리 안에서 레코드 수 줄이기
- Hive는 데이터베이스가 아닌 **데이터 처리**를 위한 배치 처리 구조임 → **데이터의 양**을 의식하면서 쿼리를 작성해야 한다.
① 비효율적인 쿼리 SELECT ... FROM access_log a JOIN users b ON b.id = a.user_id WHERE b.created_at = '2017-01-01'
- 팩트 테이블("_**access_log**_")와 디멘전 테이블("_**user**_")을 결합하고 WHERE로 조건을 부여하는 쿼리
- 모든 데이터를 읽어들인 후 WHERE 조건 검색
- 대량의 중간 데이터가 생성되고, 대부분은 그냥 버림 → 낭비
<br>
② 보다 효율적인 쿼리 SELECT ... FROM ( SELECT * access_log WHERE time >= TIMESTAMP '2017-01-01 00:00:00' ) a JOIN users b ON b.id = a.user_id WHERE b.created_at = '2017-01-01'
![image](https://github.com/chominyeong/BIG-DATA-WO-SASAERU-GIJUTSU/assets/81460659/d1053227-b3a6-4a19-8154-74e1b30ae00c)
- **서브 쿼리** 안에 **팩트 테이블**을 작게 생성한다.
<br>
#### 👉 데이터 편향 피하기
> **분산 시스템**의 성능 발휘를 위해
- 중복이 없는 값을 추출(_distinct count_)하기 위해서는 데이터를 한 곳에 모아야 한다. → **분산처리가 어려워짐**
1. **일별** 고유 유저 수의 추이 확인
① 비효율적인 쿼리 SELECT date, count(distinct user_id) users #distinct count는 분산되지 않음 FROM access_log GROUP BY date
- distinct count는 분산되지 않아도 GROUP BY에 의한 그룹화는 분산 처리된다.
ex. 30일 동안의 데이터 → 30으로 분할, 충분히 고속으로 실행(but 하루 데이터 양이 거의 균등하다는 조건 하에 이루어짐. 데이터에 편차가 있다면 문제 발생)
2. **웹페이지당** 고유 방문자 수 확인
② 보다 효율적인 쿼리 SELECT date, count(*) useres FROM ( SELECT DISTINCT date, user_id FROM access_log #애초에 중복을 없앰 ) t GROUP BY date
- 웹페이지별로 조회수에는 차이가 존재 → 편차 발생
- **SELECT DISTINCT** 사용
<br>
### 2-b. Presto로 비정규화 테이블 만들기
#### 👍 플러그인 가능한 스토리지
![image](https://github.com/chominyeong/BIG-DATA-WO-SASAERU-GIJUTSU/assets/81460659/1831cbbc-7e6e-4351-aebb-af8ad6494df3)
> 하나의 쿼리 안에서 여러 데이터 소스에 연결 가능
- **Presto**는 데이터 소스에서 직접 데이터를 읽어 들인다.
- 일반적인 MPP DB → 데이터를 로드하지 않으면 집계 시작 불가
- **Presto**는 **Hive 메타 스토어**에 등록된 테이블을 가져올 수 있다.
- _Presto_ 는 **열 지향 데이터**에서 뛰어난 성능을 보인다. → 확장성이 높은 **분산 스토리지**에 배치해서 성능 발휘
- _Presto_ 클러스터를 분산 스토리지와 네트워크의 가까운 곳에 설치한 후 가능한 한 고속 네트워크에 연결하면 데이터의 로딩 속도를 높일 수 있다.
<br>
#### 👍 CPU 처리의 최적화
- Presto는 쿼리를 분석하여 **최적의 실행 계획** 생성 → **바이트 코드**로 변환 → 이 바이트 코드가 **Presto의 워커 노드**에 배포됨 → 런타임 시스템에 의해 **기계 코드로 컴파일** 된다
- 코드는 멀티 스레드화되어 단일 머신에서 수백 태스크 or 병렬로 실행된다. + 열지향 스토리지에서의 읽기도 병렬화되어 데이터가 도달할 때마다 처리가 진행됨
- →Presto의 CPU 이용 효율이 높기 때문에, **메모리와 CPU 리소스**만 충분하면 **데이터의 읽기 속도**가 쿼리의 실행 시간을 결정하게 된다.
- Presto 쿼리는 실행되면 중간에 끼어들 수 없음 → 너무 큰 쿼리 실행하면 안됨
- 대부분의 쿼리는 단시간에 종료해 리소스가 해제됨
#### 👍 인 메모리 처리에 의한 고속화
- Presto는 쿼리의 실행 과정에서 디스크에 쓰기를 하지 않는다.
- Presto는 모든 데이터 처리를 **메모리상에서** 실시하고 메모리가 부족하면 여유가 생길 때까지 기다리거나 오류로 실패한다.
- 메모리 할당을 늘리거나 쿼리를 다시 작성해 메모리 소비를 줄여야 한다.
- 데이터 양이 많아도 메모리 소비는 늘어나지 않는다.
- GROUP BY는 단순 반복이므로 메모리 소비량은 고정이다.
- 메모리상에서 할 수 있는 것은 메모리에서, 디스크가 있어야 하는 task는 Hive에서 실행
#### 👍 분산 결합과 브로드캐스트 결합
![image](https://github.com/chominyeong/BIG-DATA-WO-SASAERU-GIJUTSU/assets/81460659/9cc5b090-e88c-4093-9c98-a62ea5a88c4e)
- 2개의 팩트 테이블을 결합하는 경우는 **분산 결합(distribute join)** 실시
- 매우 많은 조인 키를 메모리상에 계속 유지해야 함
- 같은 키를 갖는 데이터는 동일한 노드에
![image](https://github.com/chominyeong/BIG-DATA-WO-SASAERU-GIJUTSU/assets/81460659/bd9ecc2f-4375-4679-9d71-1ef0f7341772)
- 한쪽 테이블이 작은 경우에는 **브로드캐스트 결합(broadcast join)** 실시
- 결합하는 테이블의 모든 데이터가 각 노드에 복사됨
- **팩트 테이블은 냅두고, 디멘전 테이블은 여러 개 복사**
- Presto에서 **브로드캐스트 결합**을 하려면 **분산 결합은 명시적으로 무효화**해야 한다. + 쿼리 안의 SELECT 문으로 **먼저 팩트 테이블을 지정**하여 거기에 디멘전을 결합해야 한다.
#### 👍 열 지향 스토리지 집계
$ presto --catalog hive --schema default
presto:default> SELECT status, count(*) cnt -> FROM access_log_orc GROUP BY status LIMIT 2; status | cnt -------+-------- 200 | 1701534 302 | 46573 (2 rows)
Query 20170520_152030_00005_u8m9e, FINISHED, 1 node Splits: 50 total, 50 done (100.00%) 0:00 [1.89M rows, 7.96MB] [4.85M rows/s, 20.4MB/s]
<br><br>
<details><summary>🔩</summary>
<p>
비구조화 데이터 ---(데이터 구조화)---> 구조화 데이터(열지향 스토리지) ---(데이터 집약)---> 비정규화 테이블(데이터 마트)
</p>
</details>
3-1 대규모 분산 처리의 프레임워크
📁 구조화 데이터(structured data)
📁 비구조화 데이터(unstructured data)
📁 반구조화 데이터 = 스키마리스 데이터(schemaless data)
👉 데이터 구조화의 파이프라인
👉 열 지향 스토리지의 작성
정리
비구조화 데이터 --- (분산 처리 프레임워크) ---> 열 지향 스토리지로 변환
🐘 Hadoop
Hadoop은 분산 시스템을 구성하는 다.수.의 소프트웨어로 이루어진 집합체다.
Hadoop의 구성요소
분산 파일 시스템(distributed file system) : HDFS(Hadoop Distributed File System)
리소스 관리자(resource manage) : YARN(Yet Another Resource Negotiator)
분산 데이터 처리(distributed data processing) : MapReduce
그 외의 프로젝트는 Hadoop 본체와는 독립적으로 개발되어 Hadoop을 잉요한 분산 애플리케이션으로 동작한다.
모든 분산 시스템이 Hadoop에 의존하는 것은 아님 ex. 분산 파일 시스템 - HDFS, 리소스 관리자 - Mesos, 분산 데이터 처리 - Spark 사용 가능
💾 HDFS
💾 YARN
💾 MapReduce
💫 Spark
→ Spark는 Hadoop이 아닌, MapReduce를 대체한다.