Hive 데이터 입력시 노드당 처리 파티션 개수 초과 오류

 

·       Version : Hive

 

파티셔닝된Hive 테이블에 데이터 입력시 아래와 같은 오류가 발생하였다. 오류 메시지를 살펴보면 노드당 최대 동적 파티션 개수보다 많은 수의 동적 파티션이 생성되어 발생한 오류이다.

Error: java.lang.RuntimeException: org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing row {“col_1”:25513237,“col_2”:8104666,“col_3”:3808,“col_4”:6705,“col_4”:“2016-01-21 08:31:33",“col_6”:42,“col_7”:“471.00”,“col_8”:null} at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.map(ExecMapper.java:157) at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:54) at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:465) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:349) at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:174) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:422) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1875) at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:168) Caused by: org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing row {“col_1”:25513237,“col_2”:8104666,“col_3”:3808,“col_4”:6705,“col_5”:“2016-01-21 08:31:33",“col_6”:42,“col_7”:“471.00”,“col_8”:null} at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:494) at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.map(ExecMapper.java:148) ... 8 more Caused by: org.apache.hadoop.hive.ql.metadata.HiveFatalException: [Error 20004]: Fatal error occurred when node tried to create too many dynamic partitions. The maximum number of dynamic partitions is controlled by hive.exec.max.dynamic.partitions and hive.exec.max.dynamic.partitions.pernode. Maximum was set to 100 partitions per node, number of dynamic partitions on this node: 101 at org.apache.hadoop.hive.ql.exec.FileSinkOperator.getDynOutPaths(FileSinkOperator.java:951) at org.apache.hadoop.hive.ql.exec.FileSinkOperator.process(FileSinkOperator.java:722) at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:882) at org.apache.hadoop.hive.ql.exec.SelectOperator.process(SelectOperator.java:95) at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:882) at org.apache.hadoop.hive.ql.exec.TableScanOperator.process(TableScanOperator.java:130) at org.apache.hadoop.hive.ql.exec.MapOperator$MapOpCtx.forward(MapOperator.java:146) at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:484) ... 9 more

 

Hive 노드당 최대 동적 파티션 기본값은 100으로 설정되어 있다. 문제를 해결하기 위해서는 아래와 같은 명령을 사용하여 노드당 최대 동적 파티션 갯수 설정을 변경할 있다.

set hive.exec.max.dynamic.partitions=100000;
set hive.exec.max.dynamic.partitions.pernode=100000;

 

노드당 파일 갯수 초과할 경우에도 비슷한 오류가 발생한다. 아래 같은 오류 구문이 발생 때에는 파일 갯수의 설정을 오류가 발생한 최대 값보다 크게 설정할 있도록 한다.

[Fatal Error] total number of created files now is 100028, which exceeds 100000. Killing the job.

 

set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=100000;
set hive.exec.max.dynamic.partitions=100000;
set hive.exec.max.created.files=900000;

 

 

위와 같이 설정값을 변경하기에 앞서 Hive에서 이렇게 많은 파티션 또는 파일을 생성하는지 생각해보아야 한다. 대부분의 경우 사용자 설정값 범위 내에서 파티션이 이루어진다는 가정하에 사용하는데,  이렇게 한계를 벗어난 다는 것은 파티션 키를 잘못 배치했거나 파티션 처리에 적절하지 않는 데이터셋을 사용했을 가능성이 크다. 그럼에도 불구하고 파티션을 늘려야한다고 생각되면 옵션을 사용하여 적절할 임계치를 조절할 있도록 한다.

 

2021-09-13 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, 파티션 테이블, 동적 파티션 개수 초과,

Hive UDF (사용자 정의 함수)

 

·       Version : Hive

 

Hive UDF(User Define Function, 사용자 정의 함수) 사용자에게 HiveQL 확장할 있게 해주는 하이브의 강력한 기능이다. 자바를 이용해 구현하며 세션에 추가되면 마치 내장 함수처럼 동작하고 심지어 온라인 도움말도 제공할 있다. UDF 사용하면 하이브 쿼리가 동작하는 동일한 프로세스 안에서 마치 태스크처럼 돌아간다. 그러므로 효과적으로 동작하고 다른 시스템과의 통합 과정에서 발생하는 복잡함을 제거할 있다.

 

현재 하이브 세션에 로드된 내장함수는 SHOW FUNCTIONS 명령어를 사용하여 목록을 확인할 있다.

hive>show functions;

 

함수는 보통 자신을 설명하는 문서를 가지고 있으며 DESCRIBE FUNCTION 명령어를 사용하여 간략한 설명을 볼수 있다. EXTENDED 예약어로 확장 문서를 확인할 수도 있다.

hive>describe function concat;

 

hive>describe function extended concat;

 

함수를 사용할면 쿼리 안에서 필요한 인자를 넣고 간단히 이름으로 호출하면 된다. 어떤 함수는 지정된 개수의 인자를 받기도 하며, 어떤 함수는 인자와 데이터 형식을 받기도 하는등, 함수에 따라 필요 인수가 다를수 있다.

일반적으로 표준함수라 불리는, 하나의 로우 또는 하나 이상의 컬럼을 받아서 하나의 값을 반환하는 함수는 데이터형을 변환 (DOUBLE-> BIGINT)하거나 round(), floor(),  절대값을 계산하는 abs() 함수 같은 수학함수가 있으며, 대소문자 전환, 문자열 뒤집기, 문자열 연결등과 같은 문자열 조작 함수 등이 있다.

 

집계함수(aggregate function) 사용자 정의와 내장된 모든 집계 함수를 포함하여 0 이상의 로우 또는 하나 이상의 컬럼을 받아서 하나의 결과값을 반환한다. 대표적인 함수로 sum(), avg(), min(), max() 등이 있다.

 

테이블 생성함수(table generating function 0 또는 이상의 입력을 받아서 여러 컬럼 또는 로우를 결과값으로 생성한다. 대표적으로 array 함수가 있으며, explode() 함수는 배열을 입력받아서 배열의 요소를 ROW 반환한다.

 

2020-11-12 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, 하이브 사용자 함수, 하이브 UDF, Hive UDF, User Define Function, Hive Function

Hive Thrift Service (쓰리프트 서비스)

 

·       Version : Hive

 

Hive 하이브 서버(Hive Server) 또는 하이브 쓰리프트(Hive Thrift) 불리는 구성요소를 가지고 있다. 쓰리프트는 확장성과 서로 다른 언어간에 통신이 가능한 소프트웨어 프레임워크이다. 구성요소를 통해 클라이언트는 하나의 포트(Port) 하이브에 접근할 있다.

CLI 하이브를 접근하는 가능 일방적인 방식이다. CLI 모든 하이브 구성요소 설정이 로컬에 복사본으로 존재해야만 동작한다. 마찬가지로 하둡 클리아언트와 하둡 설정도 있어야 한다. 하이브 CLI HDFS 클라이언트, 맵리듀스 클라이언트, JDBC 클라이언트(메타스토어 접속용) 동작한다.

 

하이브 서비스는 쓰리프트를 이용한다. 쓰리프트는 인터페이스 언어를 제공한다. 쓰리프트 컴파일러는 인터페이스를 해석하여 다양한 언어로 네트워크 RPC 클라이언트 코드를 생성한다. 하이브는 자바로 작성되었고, 자바 바이트 코드(bytecode) 범용 플랫폼이므로 쓰리프트 서버를 위한 자바 클라이언트를 하이브 배포에 포함하고 있다. 클라이언트를 사용하는 방법중 하나는 자바 통합 개발 환경으로 프로젝트를 시작해 관련 라이브러리를 직접 포함시키거나 메이븐을 통해 가져오는 방법이 있다.

 

하이브 서비스는 쓰리프트를 통해 하이브 메타스토어에 접속한다. 일반적으로 사용자는 메타스토어를 직접 수정하는 메타스토어 메소드를 사용하지 말고 하이브를 통해 HiveQL 언어를 이용해야한다. 사용자는 테이블에 관한 메타 정보만 제공하는 읽기 전용 메소드를 사용하는것이 좋다.

 

하이브 CLI /tmp hadoop.tmp.dir 디렉터리에 .hivehistory 같은 산출물을 만들어 낸다. 하이브 서비스는 하둡 잡이 실행되는 시작점이기 때문에 하이브 서비스를 배치할 몇가지 고려할 점이 있다. 특히 클라이언트 장비에서하던 태스크 계획, 관리 작업이 서버에서 실행되기 때문에 여러 클라이언트의 동시 실행시 서비스 오버헤드를 줄이기 위하 부하 분산으로 TCP load balance 이용하거나 백엔스 서버의 pool 접속하는 프록시를 만들어 사용하는것이 좋다. 또한 하이브는 hive.start.cleanup.scratchdir 이라는 속성을 통해 재시작시 scratch 디렉터리를 비운다. 기본값은 false이며, true 변경하여 재시작시 디렉터리를 클린업 있다.

 

일반적으로 하이브 세션은 메타스토어로 이용하는 JDBC 데이터베이스에 직접 연결된다. 하이브는 쓰리프트 메타스토어(ThriftMetastore)라는 선택적 구성요소를 제공하는데, 이를 설치하면 하이브 클라이언트는 쓰리프트 메타스토어로 연결되고 쓰리프트 메타스토어가 JDBC 데이터베이스에 연결된다.

 

 

 

 

 

2020-11-08 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 쓰리프트, Hive Thrift, 하이브 관리, Hive Management

Hive 보안 인증, 권한 부여

 

·       Version : Hive

 

하둡은 보안강화를 위해 커버로스(Kerberos)인증을 지원한다. 커버로스 인증은 서버와 클라이언트 간의 상호 인증을 지원한다. 더이상 hadoop. job.ugi 속성을 설정하여 다른 사용자인척 없다. 하지만 이렇게 동작하려면 모든 하둡 구성요소는 커버로스 보안을 양쪽 끝에서 지원해야한다.  모든 하둡 에코 시스템이 커버로스 인증을 지원 못하듯이, 하이브 인증도 완전하지 않다. 하이브는 메타스토어에 접속하기 위해서 JDBC 데이터베이스 연결을 사용하거나 사용자를 대신해서 동작을 수행하는 쓰리프트를 사용한다. 쓰리프트 기반의 하이브 서비스 역시 다른 사용자인척 해야한다. 소유자와 그룹이 파일에 대한 소유권을 갖는 하둡의 파일 소유 모델은 테이블에서 로우나 컬럼 기반 방식으로 접근을 허용하고 금지하도록 구현된 많은 데이터베이스의 방식과 다르다.

앞에 설명한 파일 소유 모델 때문에 파일과 디렉터리의 소유가 서로 다른 사용자라면 파일에 퍼미션(permission) 부여하는 일이 중요하다.  HDFS 퍼미션 시스템은  user, group, others 요소가 있으며 read, write, execute라는 퍼미션이 있다. 하이브는 hive.files.umask.value 속성을 가지고 있는데 설정으로 새롭게 생성하는 파일의 기본 퍼미션을 비트 마스크를 통해서 설정한다. Hadoop Hive 사용자의 구성에 따라 664 권한인 0002 파일 권한 비트 마스크를 만들 있다.

<property> 

  <name>hive.files.umask.value</name> 

  <value>0002</value> 

  <description>The dfs.umask value for the hive created folders</description> 

</property>

 

hive.metastore.authorization.storage.checks 속성을 true 설정하면 테이블 내부에 사용자가 지울 있는 퍼미션을 갖지 못한 파일이 있을때 하이브는 해당 테이블을 드롭하는 것을 방지한다. 속성의 기본값은 false 이며 true 설정해야 한다.

<property> 

  <name>hive.metastore.authorization.storage.checks</name> 

  <value>true</value> 

  <description>Should the metastore do authorization checks against 

  the underlying storage for operations like drop-partition (disallow 

  the drop-partition if the user in question doesn't have permissions 

  to delete the corresponding directory on the storage).</description> 

</property>

 

동시에 Hive hive.metastore.execute.setugi 가능한 true 설정한다. 안전하지 않은 모드에서 속성을 true 설정하면 메타 스토어가 사용자 그룹의 권한을 정의하는 DFS 작업을 수행한다.

 

Hive 인증을 활성화 하는 방법은 hive.security.authorization.enabled true 설정한다. 기본값은 false이다.

<property> 

  <name>hive.security.authorization.enabled</name>  

  <value>true</value> 

  <description>Enable or disable the hive client authorization</description> 

</property>

 

hive.security.authorization.createtable.owner.grants 속성에서는 테이블 생성자가 접근할 있는 권한을 구성한다. 기본값은 null이며, ALL 설정하여 사용자가 자신이 만든 테이블에 액세스 있도록 한다.

<property> 

  <name>hive.security.authorization.createtable.owner.grants</name> 

  <value>ALL</value> 

  <description>The privileges automatically granted to the owner whenever 

  a table gets created.An example like "select,drop" will grant select 

  and drop privilege to the owner of the table</description> 

</property> 

 

아래 스크립트는 Hive명령으로 사용자 인증을 활성화 한다. 권한이 없을 경우 아래 예제 스크립트와 같이 테이블 생성시 오류가 발생한다.

hive> set hive.security.authorization.enabled=true;   

 

hive> CREATE TABLE auth_test (key int, value string);   

 

Authorization failed:No privilege 'Create' found for outputs { database:default}.   

Use show grant to get more details

 

권한을 부여하기 위해서는 아래 스크립트를 사용할수 있다. 사용자(USER), 그룹(GROUP), 역할(ROLES) 같은 다양한 주제에 권한을 부여할 있다.

hive> set system:user.name; 

 

system:user.name=hadoop 

 

hive> GRANT CREATE ON DATABASE default TO USER hadoop; 

 

hive> CREATE TABLE auth_test (key INT, value STRING); 

 

Confirm the permissions we have with the SHOW GRANT command:

hive> SHOW GRANT USER hadoop ON DATABASE default;   

database default   

principalName hadoop   

principalType USER   

privilege Create   

grantTime Sun May 06 17:18:10 EDT 2018   

grantor hadoop

 

사용자별로 퍼미션을 부여하는 작업은 사용자와 테이블이 많을수록 관리 부담이 증가한다. 이런경우 그룹 단위로 퍼미션을 부여할 있다. 하이브에서 그룹은 사용자의 번째 POSIX 그룹과 동일하다.

hive> CREATE TABLE auth_test_group(a int,b int); 

 

hive> SELECT * FROM auth_test_group;

 

Authorization failed:No privilege 'Select' found for inputs 

{ database:default, table:auth_test_group, columnName:a}. 

Use show grant to get more details. 

hive> GRANT SELECT on table auth_test_group to group hadoop; 

hive> SELECT * FROM auth_test_group; 

OK 

Time taken: 0.119 seconds

 

사용자와 그룹 퍼미션이 충분히 유연하지 않은경우 역할(role) 사용할 있다. 사용자에게 역할을 부여하고 특권이 역할에 부여될수 있다. 시스템 외부에서 제어하는 그룹과는 달리 역할은 하이브 내부에서 제어되므로 좀더 유연성을 제공한다.

hive> set system:user.name; 

 

system:user.name=hadoop 

 

hive> GRANT CREATE ON DATABASE default TO USER hadoop; 

 

hive> CREATE TABLE auth_test (key INT, value STRING); 

 

Confirm the permissions we have with the SHOW GRANT command:

hive> SHOW GRANT USER hadoop ON DATABASE default;   

database default    

principalName hadoop   

principalType USER   

privilege Create   

grantTime Sun May 06 17:18:10 EDT 2018   

grantor hadoop

 

기본적으로 파티션 테이블의 권한은 테이블의 권한을 따르거나  파티션에 대한 권한 메커니즘을 설정할 있다. 테이블 속성의 PARTITION_LEVEL_PRIVILEGE true 설정하여 사용할 있다.

hive> ALTER TABLE auth_part 

> SET TBLPROPERTIES ("PARTITION_LEVEL_PRIVILEGE"="TRUE"); 

Authorization failed:No privilege 'Alter' found for inputs 

{database:default, table:auth_part}. 

Use show grant to get more details.

 

일반 사용자는 쿼리를 수행하기 위해서 스스로 특권을 부여하는 번거로움 없이 테이블을 생성하고 싶을 것이다. 또는 기본 동작으로 모든 특권을 부여하여 사용하고 싶을 것이다. 아래 스크립트는 SELECT DROP 특권을 자신 소유의 테이블에 자동으로 권한을 부여한다.

<property> 

  <name>hive.security.authorization.createtable.owner.grants</name> 

  <value>select,drop</value> 

</property>

 

비슷하게 특정 사용자는 생성한 테이블에 대한 특권을 자동으로 부여받을수 있다. 아래 스크립트는 sungwook, sqlmvp 사용자가 모든 테이블을 읽을수 있는 권한을 부여한다. 그리고 tom 테이블 생성만 가능하다.

<property> 

  <name>hive.security.authorization.createtable.user.grants</name> 

  <value>sungwook,sqlmvp:select;tom:create</value> 

</property>

 

동일한 구성을 그룹 권한 역할 권한에도 적용할 있다.

hive.security.authorization.createtable.group.grants 

hive.security.authorization.createtable.role.grants

 

권한을 회수하는 방법은 아래 스크립트를 사용한다.

revoke create on database default from user sungwook;

revoke select on database default from group sungwook; 

 

 

 

[참고자료]

·       Hive - Authority Management (Authorization) : https://www.programmersought.com/article/1095315821/

 

 

2020-10-27 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, 하이브 보안, 하이브 인증, 하이브 권한, Hive Security, Hive Authorization, Hive Authority Management

Hive 잠금(lock)

 

·       Version : Hive

 

HiveQL SQL 유사하지만 잠금(locking) 대한 메커니즘은 완전히 다르다. SQL 비교한다면 매우 부족한 lock 모델을 가지고 있다. 하둡이 제한된 의미의 이어쓰기 (append) 지원하고 있지만 전통적으로는 write-once(한번쓰면 변경이 불가능하다는 의미) 특성을 가지고 있기 때문에 이러한 특성과 맵리듀스의 스트리밍 읽기 방식으로 인해 세밀한 잠금에 대한 접근은 불필요하기 때문이다.

그러나 하둡은 다중 사용자 시스템이기 때문에 잠금과 코디네이션이 필요할수도 있다. 예를들어 INSERT OVERWRITE 쿼리는 테이블의 모든 내용을 덮어쓰고 다른 사용자가 동시에 테이블에 쿼리를 시도하면 쿼리가 실패하거나 잘못된 결과를 반환할 있기 때문에 명시적으로 테이블에 잠금이 필요할 수도 있다.

하이브는 아파치 주키퍼(Apache Zookeeper) 이용하여 잠금을 제공한다. 주키퍼는 분산 코디네이션을 구현한 오픈소스로 Kafka 분산 코디네이션이 필요한 환경에서 많이 사용 한다. 하이브에서 주키퍼를 코디네이션으로 사용하려면 주피커 쿼럼 노드를 등록해야한다. hive-site.xml에서 설정할 있다.

#통신할 주키퍼 목록을 등록, 읽기/쓰기 잠금을 위해서만 필요

<property>

  <name>hive.zookeeper.quorum</name>

  <value>hadoopcluster01:2181,hadoopcluster02:2181</value>

</property>

 

#동시성을 제공할지 설정, 최소 하나의 주키퍼가 등록되어 있어야 한다.

<property>

  <name>hive.support.concurrency</name>

  <value>true</value>

</property>

 

설정으로 하이브는 쿼리를 실행할때 자동으로 잠금이 지원되며 현재 모든 잠금 목록을 확인하기 위해서는 아래 스크립트를 실행한다.

hive> show locks;

hive>show locks 테이블명 extended;

 

동시성 기능이 true 설정되어 있는 경우 하이브는 자동으로 가지 종류의 잠금 기능을 제공한다. 테이블을 읽을 때에는 공유 잠금(shared lock) 사용하고, 테이블을 수정할 때는 배타적 잠금(exclusive lock) 사용한다. 테이블이 파티션닝 되어 있을때 파티션에 대한 베타적 잠금을 얻게 되면 파티션이 수정되는 동안 테이블 삭제 시도와 같은 동시 변경이 발생되지 못하도록 테이블 자체에 공유 잠금을 건다. 베타적 잠금은 테이블의 모든 파티션에 영향을 미친다.

 

명시적으로 잠금을 관리할수도 있으며 아래 스크립트는 명시적으로 베타 잠금을 생성한다.

hive>lock table 테이블명 exclusive;

 

명시적 잠금 해제는 unlock 명령을 사용한다.

hive>unlock table 테이블명;

 

 

[참고자료]

https://cloudera.ericlin.me/2015/05/how-table-locking-works-in-hive/

 

 

 

 

2020-10-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, 하이브락, hive lock, 하이브 잠금

Hive 투기적 실행(Speculative execution)

 

·       Version : Hive

 

Hive에서 투기적 실행(Speculative execution)이라 불리는 기능은 하나의 잡을 중복된 태스크로 구성하여 동시에 수행 시키는 하둡의 기능이다. 같은 데이터를 중복하여 복사하기 때문에 많은 리소스를 사용하며, 대부분의 데이터는 버려진다. 기능의 목적은 느리게 동직하는 태스크 트래커를 제거함으로써 개별 태스크의 결과가 빨리 도출되고 결과적으로 전체 수행을 향상시키는데 있다.

, 동일한 태스크를 여러노드에서 실행함으로써, 특정 노드가 느리더라도 (장비 노후 또는 기타 문제로) 다른 노드에서 먼저 끝나면 해당 결과를 사용하고 나머지 노드는 중지 시킨다. 그래서 전체적으로는 수행시간이 단축된다.

Speculative execution 기능 활성화는 mapred-site.xml에서 아래 속성을 true 설정한다.

mapreduce.map.speculative

mapreduce.reduce.speculative

 

Speculative execution 기능은 실시간성이 중요한 잡의 경우 활성화 하여 사용하는 것이 전체적인 응답시간 향상에 이득이 있다. 하지만 입력 데이터 때문에 오래 걸리는 또는 리듀스 태스크에는 높은 오버헤드로 인해서 사용하지 않는것을 추천한다.

 

 

[참고자료]

·       https://community.cloudera.com/t5/Support-Questions/what-is-speculative-execution/td-p/241741

·       https://www.slideshare.net/Hadoop_Summit/t-325p210-cnoguchi

 

 

2020-10-19 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, MapReduce최적화, Map태스크, Reduce 태스크, 하이브 최적화, 투기적 실행, mapreduce.map.speculative, mapreduce.reduce.speculative, Speculative Execution

Hive 자바 가상 머신 재사용

 

·       Version : Hive

 

하둡에서 맵리듀스 태스크를 실행하면 기본적으로 자바 가상 머신이 실행되고 위에서 또는 리듀서 태스크를 실행한다. 하둡의 기본 설정은 일반적으로 포크(forked) 자바 가상 머신을 사용한다. 자바 가상 머신은 가동할 오버헤드가 있기 때문에, 가상 머신의 재사용은 하이브 성능과 매우 밀접한 관계가 있다. 특히 작은 파일을 처리해야하는 경우나 태스크 수행시간이 짧은 작업의 경우 자바 가상 머신을 재사용하면 매우 효율이 좋다. 만약 수십, 수백번의 태스크를 가진 잡을 수행할때 자바 가상 머신 인스턴스를 재사용한다면 동일한 잡에 N 재사용된다. 가상 머신의 재사용 설정은 하둡의 mapred-site.xml에서 설정할 있다.

mapred.job.reuse.jvm.num.tasks= 10

자바 가상 머신 하나당 번의 태스크를 수행할지 설정 -1 설정할 경우 제한이 없음.

 

자바 가상 머신을 재사용할 경우, 잡을 실행할때마다  가상 머신이 새로 가동되는 오버헤드를 줄일 있지만, 예약된 태스크 슬롯을 잡이 완료할 때까지 점유하고 있는 단점이 있다. 예를들어 잡이  병렬로 실행될때, 먼저 끝난 가상 머신은 유휴 상태로 대기하게 되고 마지막 작업이 완료되기 전까지다른 잡이 사용하지 못하는 상태가 된다. 물론 다른 잡은 다른 자바 가상 머신을 생성해서 사용하지만, 이러한 불균형이 지속적으로 발생한다면 리소스 병목이 발생할 있다.  

 

 

 

2020-10-14 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, MapReduce최적화, Map태스크, Reduce 태스크, 하이브 최적화, 자바 가상 머신, JVM

Hive Mapper, Reduce 개수 최적화

 

·       Version : Hive

 

하이브는 쿼리를 이상의 맵리듀스 잡으로 나누어 병렬로 처리한다. 맵리듀스는 다수의 맵퍼와 리듀서 태스크로 실행되는데 맵퍼와 리듀서의 수는 입력하는 데이터 크기, 데이터 수행 연산 종류 다양한 변수에 의존적이다. 너무 많은 맵퍼와 리듀서 태스크는 잡을 초기화 하고, 스케줄링하고 실행하기 위해 많은 오버헤드를 유발한다. 반대로 너무 적은 태스크는 클러스터가 가진 병렬처리의 장점을 활용하지 못하게 된다.

 

리듀스 단계가 있는 하이브 쿼리를 실행하면 리듀서 수를 출력한다. GROUP BY 항상 리듀서 단계가 필요하기 때문에 해당 구문이 포함한스크립트를 실행하면 사용된 맵퍼와 리듀서의 개수를 확인할 있다.

INFO  : Hadoop job information for Stage-1: number of mappers: 5; number of reducers: 1

INFO  : 2020-09-29 22:31:55,395 Stage-1 map = 0%,  reduce = 0%

INFO  : 2020-09-29 22:32:04,712 Stage-1 map = 20%,  reduce = 0%, Cumulative CPU 5.03 sec

INFO  : 2020-09-29 22:32:05,749 Stage-1 map = 60%,  reduce = 0%, Cumulative CPU 12.13 sec

INFO  : 2020-09-29 22:32:09,885 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 19.8 sec

INFO  : 2020-09-29 22:32:16,080 Stage-1 map = 100%,  reduce = 100%, Cumulative CPU 25.89 sec

INFO  : MapReduce Total cumulative CPU time: 25 seconds 890 msec

INFO  : Ended Job = job_1591911716086_1525

INFO  : MapReduce Jobs Launched:

INFO  : Stage-Stage-1: Map: 5  Reduce: 1   Cumulative CPU: 25.89 sec   HDFS Read: 610485 HDFS Write: 775295 HDFS EC Read: 0 SUCCESS

INFO  : Total MapReduce CPU Time Spent: 25 seconds 890 msec

INFO  : Completed executing command(queryId=hive_20200929223144_877a1f4b-329b-4418-831d-89bcdc466f30); Time taken: 33.485 seconds

INFO  : OK

 

하이브는 입력 크기에 따라 리듀서 개수를 정한다. fs -count 명령을 사용하여 하둡에서 사용하려는 파일을 지정하여 예상 리듀서의 개수를 확인할 있다.

hadoop fs -count /user/data/nclick/file.txt

 

결과

0            1           12469765 /user/data/nclick/file.txt

 

리듀서의 개수는 하이브 속성중  hive.exec.reducers.bytes.per.reducer 설정된 수자를 파일 크기와 나눈값으로 계산할 있다. 설정 값은 사용자마다 다를 있다. 아래 스크립트는 hive.exec.reducers.bytes.per.reducer 속성값을 수정하는 명령이다. 단위가 바이트임을 주의한다.

set hive.exec.reducers.bytes.per.reducer=75000000

 

쿼리의 단계에서 입력 데이터 크기보다 훨씬 많은 데이터를 만들어내는 경우가 있다. 단계에서 과도한 데이터를 만들어내면 입력 데이터로 추정한 기본 리듀서의 수는 부족할 있으며 비슷하게 함수가 입력 데이터의 많은 부분을 필터링 수도 있다. 그러면 기본값보다 적은 리듀서만 있어도 된다.리듀서의 태스크 수는 mapred.reduce.tasks 설정값으로 조절할 있다.

 

하둡 클러스터에는 태스크를 할당하는 고정된 크기의 슬롯이 있다. 개의큰 잡이 하둡의 모든 슬롯을 점유하면 다른 잡이 시작되지 못할 있다. hive.exec.reducers.max 설정 값을 조절하여 쿼리가 너무 많은 리듀서 자원을 사용하는 것을 예방할 있다.

 

하둡은 맵과 리듀스 태스크를 기동하고 스케줄링하는데 정도 오버헤드가 발생한다. 성능 테스트를 수행할때 이러한 요인을 염두해 두어야 하며 특히 잡의 크기가 작을수록 이러한 부분을 염두해서 테스트를 진행해야한다.

 

 

 

2020-09-29 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, MapReduce최적화, Map태스크, Reduce 태스크, 하이브 최적화

HDFS Cluster Balancing(데이터 블록 분포의 불균형 해소)

 

·       Version : HDFS

 

HDFS 시스템은 여러대의 노드가 클러스터로 동작하기 때문에 시간이 지날수록 데이터 노드의 블록 분포에 대한 불균형이 발생할 있다. 불균형 상태의 클러스터는 맵리듀스의 로컬리티에 영향을 주기 때문에 자주 사용되는 데이터노드에 많은 부하를 주게 된다. 따라서 이러한 블록의 불균형 분포를 해결하기 위해 밸런서 작업으로 블록을 재분배 하여 전체적으로 블록을 고르게 유지할 있도록 다른 노드로 블록을 이동한다. 이때 데이터 유실을 방지하기 위해 데이터 블록 복제본의 배치전략은 유지된다. 밸런서를 실행하는 명령은 아래와 같다.

sudo -u hdfs hdfs balancer

 

 

노드의 균형은 노드들의 이용률(노드에서 사용중인 공간 비율과 저장공간의 비율), 클러스터의 이용률(클러스터에서 사용중인 공간과 저장공간의 비율) 비교하여 임계치 보다 적을때 까지 실행된다. 임계치는 기본 10% 이며 클러스터에는 오직 하나의 밸런서만이 실행될 있다. 임계치 변경은 아래 명령으로 변경할 있다.

sudo -u hdfs hdfs balancer -threshold 5

 

밸런서 작업중 노드 이동에 대한 기본 대역폭은 1MB/s 이지만 hdfs-site.xml에서 dfs.balance.bandwidthPerSec 속성에서 대역폭을 설정 있으며 단위는 byte이다. 아래 명령으로도 설정이 가능하다.

dfsadmin -setBalancerBandwidth  newbandwidth

 

 

 

[참고자료]

·       How-to: Use the New HDFS Intra-DataNode Disk Balancer in Apache Hadoop : https://blog.cloudera.com/how-to-use-the-new-hdfs-intra-datanode-disk-balancer-in-apache-hadoop/

·       HDFS Balancers : https://docs.cloudera.com/documentation/enterprise/5-12-x/topics/admin_hdfs_balancer.html

 

 

 

 

2020-09-25 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, 데이터 블록 불균형, 노드 밸런서, 하둡 밸런서, Hadoop Balancer, Cluster Balancing, 하둡 튜닝, 하둡 관리, HDFS 관리

Hive LIMIT 튜닝 (데이터 샘플링으로 빠르게 응답하기)

 

·       Version : Hive

 

하이브에서 현재 저장되어 있는 데이터의 일부분을 확인하려고 LIMIT 절을 자주 사용한다. RDB 경우 데이터를 ROW단위로 읽기때문에(정확히는 페이지 단위) ROW단위로 처리하면서LIMIT 결과를 (Sort, Group 연산을 하지 않았을 경우) 빠르게 응답할 있다.  하지만 하이브의 경우 데이터 전체에 대해 쿼리를 수행하고 일부 결과만을 반환하기 때문에 불필요한 리소스 낭비가 크다. 그래서 최대한 LIMIT 명령을 피하는 것이 좋다.

만약 limit 자주 사용할 경우 hive-site.xml 파일에서 hive.limit.optimize.enable설정을 통해서  LIMIT 사용할 경우 원본 데이터를 샘플링 있다.

<property>

       <name>hive.limit.optimize.enable</name>

       <value>false</value>

       <description>Whether to enable to optimization to trying a smaller subset of data for simple LIMIT first.</description>

</property>

 

hive.limit.optimize.enable 옵션을 True 설정하면 hive.limit.row.max.size hive.limit.optimize.limit.file 제어할 있다.

<property>

       <name>hive.limit.row.max.size</name>

       <value>100000</value>

       <description>When trying a smaller subset of data for simple LIMIT, how much size we need to guarantee each row to have at least.</description>

</property>

 

<property>

       <name>hive.limit.optimize.limit.file</name>

       <value>10</value>

       <description>When trying a smaller subset of data for simple LIMIT, maximum number of files we can sample.</description>

</property>

 

하지만 기능은 JOIN이나 GRPUP BY 같이 리듀스 과정이 필요한 모든 쿼리에서는 결과 값이 달라지기 때문에 주의해야 한다.

 

 

 

2020-09-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, limit tunning, Limit Optimize, limit sampling

HDFS 데이터노드 블록 스캐너 (손상된 블록을 검색하여 수정)

 

·       Version : HDFS

 

HDFS 에서 데이터를 쓰거나 읽을때 체크섬을 사용하여 데이터 손상을 확인하고 수정한다. 이러한 작업으로 데이터 손상을 감지 있지만 해당 작업은 데이터를 쓰거나 읽을때만 발생하므로 클라이언트가 데이터를 요청하기 전에는 손상된 부분을 찾는것이 쉽지 않다. 이러한 손상된 부분을 찾기 위해 모든 데이터노드는 블록스캐너를 실행하여 데이터노드에 저장된 모든 블록을 주기적으로 점검한다. 작업으로 문제 있는 블록은 클라이언트가 읽기 전에 삭제하거나 수정한다.

데이터 블록 스캐너는 점검할 블록 리스트를 관리하며 체크섬 오류를 찾기 위해 모든 블록들을 점검한다. 스캐너는 데이터노드의 디스크 대역폭을 보존하기 위한 조절 메커니즘을 사용한다. 데이터 블록 스캔 주기는 hdfs-site.xml 파일에 dfs.datanode.scan.period.hours 속성 값으로 제어할 있며 단위는 시간(hour)이다. 속성값을 0 으로 설정시 데이터 블록 스캔 작업을 비활성화 한다.

블록 스캐너가 실행될때마다 보고서가 생성되며 데이터 노드의 인터페이스 URL에서 보고서를 확인할 있다.

http://datanode:50075/blockScannerReport

 

 

 

2020-09-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, 체크섬 오류, 하둡 데이터 복구, 데이트 블록 스캔, Data block scan, Corrupted blocks, Block Scanner report

Hive EXPLAIN (실행계획) 사용

 

·       Version : Hive

 

하이브에서 EXPLAIN 명령을 사용하면 실행계획을 확인할 있다. , 쿼리를 어떻게 맵리듀스 잡으로 변환하지를 살펴 있다. 실행계획을 사용하는 방법은 아래 스크립트 처럼 쿼리문 앞에 EXPLAIN 명령을 함께 실행한다.

EXPLAIN

SELECT

       col_1, date_local, count(*) as cnt

FROM tbl_a

where col_1 = 'aaa.com'

group by date_local, col_1;

 

아래 실행 계획은 쿼리를 실행하였을때 반환된 결과이다.

1      STAGE DEPENDENCIES:

2        Stage-1 is a root stage

3        Stage-0 depends on stages: Stage-1

4     

5      STAGE PLANS:

6        Stage: Stage-1

7          Map Reduce

8            Map Operator Tree:

9                TableScan

10                 alias: tbl_a

11                 filterExpr: (col_1 = 'aaa.com') (type: boolean)

12                 Statistics: Num rows: 5275084 Data size: 1039193932 Basic stats: COMPLETE Column stats: PARTIAL

13                 Filter Operator

14                   predicate: (col_1 = 'aaa.com') (type: boolean)

15                   Statistics: Num rows: 2637542 Data size: 485307728 Basic stats: COMPLETE Column stats: PARTIAL

16                   Select Operator

17                     expressions: date_local (type: string)

18                     outputColumnNames: date_local

19                     Statistics: Num rows: 2637542 Data size: 485307728 Basic stats: COMPLETE Column stats: PARTIAL

20                     Group By Operator

21                       aggregations: count()

22                       keys: date_local (type: string), 'aaa.com' (type: string)

23                       mode: hash

24                       outputColumnNames: _col0, _col1, _col2

25                       Statistics: Num rows: 1010 Data size: 291890 Basic stats: COMPLETE Column stats: PARTIAL

26                       Reduce Output Operator

27                         key expressions: _col0 (type: string), 'aaa.com' (type: string)

28                         sort order: ++

29                         Map-reduce partition columns: _col0 (type: string), 'aaa.com' (type: string)

30                         Statistics: Num rows: 1010 Data size: 291890 Basic stats: COMPLETE Column stats: PARTIAL

31                         value expressions: _col2 (type: bigint)

32           Reduce Operator Tree:

33             Group By Operator

34              aggregations: count(VALUE._col0)

35               keys: KEY._col0 (type: string), 'aaa.com' (type: string)

36               mode: mergepartial

37               outputColumnNames: _col0, _col1, _col2

38               Statistics: Num rows: 202 Data size: 58378 Basic stats: COMPLETE Column stats: PARTIAL

39               Select Operator

40                 expressions: 'aaa.com' (type: string), _col0 (type: string), _col2 (type: bigint)

41                 outputColumnNames: _col0, _col1, _col2

42                 Statistics: Num rows: 202 Data size: 58378 Basic stats: COMPLETE Column stats: PARTIAL

43                 File Output Operator

44                   compressed: false

45                   Statistics: Num rows: 202 Data size: 58378 Basic stats: COMPLETE Column stats: PARTIAL

46                   table:

47                       input format: org.apache.hadoop.mapred.SequenceFileInputFormat

48                       output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat

49                       serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe

50    

51       Stage: Stage-0

52         Fetch Operator

53           limit: -1

54           Processor Tree:

55             ListSink

56    

 

·       1 ~ 2 : 하이브 잡은 하나 이상의 스테이지(stage) 구성된다. 스테이지 사이에는 의존관계가 있으며 복잡한 쿼리는 많은 스테이지로 구성되며 많은 시간이 소요된다. 스테이지는 맵리듀스 스테이지, 샘플링(sampling) 스테이지, 병합 스테이지, limit 스테이지 하이브가 필요한 일을 하는 스테이지로 구성된다. 하이브는 스테이지를 하나씩 실행한다.

·       5 : STAGE PLANS 절은 매우 길고 복잡하다.

·       6 : 잡을 위한 처리 묶음이고 맵리듀스를 통해 실행된다.

·       7 : Map Operator Tree: 이후의 모든 부분은 잡의 부분에서 실행한다.

·       9 : TableScan 태스크는 테이블을 입력으로 받아 결과 컬럼을 만든다.

·       13 : Filter Operator에서 조회 조건을 필터 한다

·       16 : Select Operator에서 출력할 대상을 선정한다.

·       20 : Group By Operator에서 쿼리에서 요청한 카운트 작업을 한다.

·       32 : Reduce Operator Tree : 이후의 부분은 모두 리듀스 부분에서 실행한다.

·       33 : Reduce에서도 Group By Operator 확인하 있는데, 맵에서 전달받은 값을 count 한다.

·       43, 48 : 마지막으로 파일을 출력하며, 해당 문자열 출력 포맷을 사용한다.

·       51 : 쿼리에서 limit 절이 없기 때문에 Stage-0 no-op 스테이지 이다.

 

2020-09-21 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, 쿼리 실행계획, Hive 쿼리, Hive Query execution plan

Hive 인덱스(index)

 

·       Version : Hive

 

하이브 인덱스는 연산 속도를 향상시키기 위해 컬럼에 인덱스를 생성할 있으나, RDBMS 인덱스랑 다르게 기능이 많이 제한적이다. 하이브는 인덱스 데이터를 원본 테이블이 아닌 별도 테이블에 저장한다. 그래서 인덱스 생성시 별도의 디스크 공간이 필요하고 생성에 따른 비용이 발생한다. 그래서 인덱스를 생성할때 사용 유무 효율을 고려해서 생성해야 한다.

하지만 하이브에서 인덱스는 논리적 파티션의 크기가 작고 개수가 많은 경우 파티셔닝을 대신해서 사용할 있으며, 맵리듀스의 잡의 입력으로 사용할 테이블 블록을 푸루닝(pruning)하는데 도움을 있다. 위에서 언급했듯이 모든 쿼리가 인덱스로 효율적인 것은 아니므로 실행계획을 분석하여 쿼리가 어떤 인덱스를 사용하는지 확인이 필요하다.

 

아래 스크립트는 인덱스를 생성하는 예제이다. AS 절은 인덱스를 구현한 자바 클래스를 인덱스 핸들러로 지정한다.

CREATE INDEX ix_tbl_a

ON TABLE tbl_a (col_1)

AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'

WITH DEFERRED REBUILD;

 

인덱스 핸들러는 인덱스 데이터를 무조건 테이블에 저장하지 않는다. 테이블에 저장하려면 IN TABLE 절을 함께 명시한다.

CREATE INDEX ix_tbl_a

ON TABLE tbl_a (col_1)

AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'

WITH DEFERRED REBUILD

IN TABLE tbl_a_index_table

PARTITION BY (par = 'XX');

 

WITH DEFERRED REBUILD 인덱스가 비어있는 상태에서 시작한다. ALTER INDEX 구문을 사용하여 언제든지 리빌드가 가능하다. 만약 파티션을 생략하면 모든 파티션에 대해서 인덱스 리빌드가 발생한다.

ALTER INDEX ix_tbl_a

ON TABLE tbl_a

PARTITION (par = 'XX')

REBUILD;

 

인덱스 삭제는 아래 명령을 사용한다.

DROP INDEX IF EXISTS ix_tbl_a ON TABLE tbl_a;

 

아래 명령은 테이블에 생성된 모든 인덱스 정보를 나타낸다.

SHOW FORMATTED INDEX ON tbl_a;

 

 

 

 

2020-08-27 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, HIVE Index, Hive 인덱스, 하이브 인덱스, 하이브 튜닝

Hive View

 

·       Version : Hive

 

하이브에서 (View) 일반 RDBMS 뷰와 동일하게 데이터를 저장하지 않는 논리적 테이블 구조이다. 뷰는 테이블과 같은 데이터베이스에 저장되기 때문에 이름은 데이터베이스 내에서 유니크해야한다.  아래 스크립트는 하이브에서 뷰를 생성하는 예제이다.

create view vw_a

as

select

       col_1, col_2, col_3

from tbl_a

where col_1 = 'a';

 

뷰를 생성할때 새로운 컬럼 이름 전체나 일부분에 COMMENT 추가할 수도 있다. 뷰는 원본 테이블로 부터 주석을 상속받지 않는다. 뷰는 INSERT LOAD 명령의 대상으로 사용할 없으며 읽기 전용이다.

 

하이브는 뷰를 먼저 수행한 후에 쿼리를 수행한다. 그러나 옵티마이저는 뷰와 쿼리절을 하나의 실제 쿼리로 결합하여 실행할 수도 있다. 하지만 하나의 쿼리로 실행되었다고 하더라도 뷰와 뷰를 사용하는 쿼리 둘다 ORDER BY 절이나 LIMIT 절을 가지고 있으면 뷰의 개념이 적용되어 절을 먼저 수행한다.

 

 

 

2020-08-24 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, HIVE view, 하이브 , Hive , 하이브 테이블

Hive에서 샘플 데이터 추출

 

·       Version : Hive

 

하이브에서 데이터 테이블이 있을때, 일부 데이터 샘플을 추출하는 방법에 대해서 알아본다. 하이브는 테이블을 버킷으로 구성하여 샘플을 만드는 쿼리로 아래와 같은 방식으로 사용할 있으며, 예제 스크립트는 1에서 10까지 값을 가진 컬럼에서 난수를 발생시키는 rand() 함수를 사용하여 샘플 데이터를 추출한다.

select * from tbl TABLESAMPLE (BUCKET 3 OUT OF 10 ON rand());

 

 BUCKET절에서 분모는 데이터가 해시될 있는 버킷 개수를 표현하며, 분자는 선택되는 버킷 숫자이다.

 

아래 스크립트는 PERCENT 함수를 사용하여 테이블 블록의 백분율로 샘플 데이터를 추출한다.

select * from tbl TABLESAMPLE (0.1 PERCENTS);

 

 

 

2020-08-13 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, TABLESAMPLE, 샘플데이터, 랜덤데이터추출

Hive ORDER BY, SORT BY, DISTRIBUTE BY, CLUSTER BY

 

·       Version : Hive

 

하이브 또는 RDBMS에서 ORDER BY 쿼리 결과 집합에 대해서 전체 정렬을 수행한다. 하이브에서 ORDER BY 모든 데이터가 하나의 리듀서로 처리되기 때문에 데이터 셋이 클수록 시간이 오래 걸린다. ORDER BY 오랜 시간을 수행될 있기 때문에 하이브는 hive.mapred.node strict 설정되었을 경우 ORDER BY절에 대해서 LIMIT 요구한다. 기본값은 nonstrict 이다.

 

 

하이브에서 ORDER BY 대신 SORT BY 사용하면 리듀서에서 지역 정렬하여 출력한다. ORDERSORT 사용할 경우 어떠한 컬럼이라도 지정할 수도 있고 ASC(기본값), DESC 사용하여 정렬할 수도 있다.  SORT BY 사용하는 경우 하나 이상의 리듀서로 처리될 경우 리듀서의 파일이 정렬되어 있더라도 전체적으로는 다른 리듀서의 출력된 정렬 결과가 겹치기 때문에 전체 정렬순서는 보장되지 않는다.

 

DISTRIBUTE BY 맵의 출력을 리듀서로 어떻게 나누어 보내는지를 제어한다. 하이브는 쿼리를 맵리듀스 잡으로 변환할때 내부적으로 기능을 사용하기도 한다. 기본적으로 맵리듀스는 맵퍼가 출력하는 키에 대해서 해시값을 계산하고 해시값을 이용하여 - 쌍을 가용한 리듀서로 균등하게 분산하려고 노력한다. 이때 SORT BY 사용할때 하나의 리듀서 출력이 다른 리듀서의 출력과 정렬 결과가 겹칠수 있다. 하지만 리듀서 출력 내에서는 정렬되어 있다. 하둡이 같은 데이터 레코드는 같은 리듀서로 보내는 것을 보장하기 위해서 DISTRIBUTE BY 사용할 있다. 그리고 리듀서 별로 데이터를 정렬하기 위해 SORT BY 사용한다.

 

 

SORT BY 리듀서 안에서 데이터 정렬을 제어하는 반면 DISTRIBUTE BY 리듀서가 처리할 로우를 어떻게 받는지 제어한다는 점에서는 GROUP BY처럼 동작한다. 하이브는 SORT BY 전에 DISTRIBUTE BY 절을 사용할 것을 요구하므로 주의해야한다.

 

CLUSTER BY 같은 쿼리를 표현하는 간단한 방법이다.

 

 

2020-08-03 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, 하이브 정렬,  ORDER BY, SORT BY, DISTRIBUTE BY, CLUSTER BY

Hive Map-Side-Join,  Bucket-Map-Join, Sort-Merge-Join

 

·       Version : Hive

 

Hive에서 조인 명령을 실행할때, 크기가 작은 테이블은 메모리에 캐시하고 크기가 테이블은 맵퍼로 흘려 보낼 있다. 하이브는 메모리에 캐시한 작은 테이블로 부터 일치하는 모든 것을 찾아 있기 때문에 맵에서 모든 조인을 있다. 이렇게 하면 일반 조인 시나리오에서 필요한 리듀스 단계를 제거할 있다.

 

데이터가 작을 수록 사이드 조인은 일반 조인보다 효율이 좋다. 리듀스 단계를 제거할 뿐만 아니라 단계 역시 줄어들기 때문이다. 사이드 조인을 활성화 하기 위해서는 hive.auto.convert.join 속성을 true 설정해야한다. 기본값은 false 이다. 사이드 조인을 사용하기 위한 테이블 크기 임계치는 hive.mapjoin.smalltable.filesize 속성값을 설정한다. 단위는 바이트 이다.

hive> set hive.auto.convert.join=true;

hive> set hive.auto.convert.join.noconditionaltask=true;

hive> set hive.auto.convert.join.noconditionaltask.size=20971520

hive> set hive.auto.convert.join.use.nonstaged=true;

hive> set hive.mapjoin.smalltable.filesize = 30000000;

 

 

사이드 조인은 특정 조건에서는 테이블에서도 사용할 있다. 이러한 조건은 ON 절에서 사용할 키에 대해서 버킷팅이 되어 있어야 하고, 테이블의 버킷 수가 다른 테이블 버킷 수의 배수이어야 한다. 이러한 조건이 충족되면 하이브는 다른 테이블의 버킷을 매칭하기 위해 모든 테이블의 내용을 가져올 필요 없이 테이블 간의 버킷에 대해 사이드 조인을 있다.   옵션을 사용하기 위해서는 hive.optimize.bucketmapjoin 속성값을 ture 설정해야 한다.

hive> set hive.optimize.bucketmapjoin=true;

 

만약 버킷팅되어 있는 테이블이 같은 수의 버킷을 가지고 있고, 데이터는 조인/버킷 키로 정렬되어 있다면 하이브는 정렬-병합 조인(Sort Merge Join) 수행하여 빠르게 조인할 있다.

 

옵션을 사용하기 위해서는 아래 설정을 활성화 해야 한다.

hive> set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;

hive> set hive.optimize.bucketmapjoin=true;

hive> set hive.optimize.bucketmapjoin.sortedmerge=true;

 

 

 

참고자료

·       Map Join in Hive | Map Side Join : https://data-flair.training/blogs/map-join-in-hive/

·       Bucket Map Join in Hive – Tips & Working : https://data-flair.training/blogs/bucket-map-join/

·       Sort Merge Bucket Join in Hive – SMB Join : https://data-flair.training/blogs/hive-sort-merge-bucket-join/

 

 

 

2020-07-28 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, JOIN, Hive Map Join, Hive Bucket Join, Hive Sort Merge Join, 조인 최적화, 하이브 튜닝

Hive Left Semi Join (세미 조인) Cartesian Product Join (카테시안 프로덕트 조인)

 

·       Version : Hive

 

Hive에서 Left Semi Join (왼쪽 세미 조인) 오른쪽 테이블에서 ON 조건을 만족하는 레코드를 찾을 경우 왼쪽 테이블의 레코드를 반환한다.

 

일반적인 RDBMS SQL 조건을 만족하기 위해 IN 또는 EXISTS 구문을 지원하지만, 하이브에서는 동작하지 않는다. 하이브는 기본적으로 Right Semi Join (오른쪽 세미 조인) 지원하지 않으며 SELECT WHERE절에서 오른쪽 테이블의 컬럼을 참조 없음에 주의해야 한다.  아래 스크립트는 하이브에서 사용할 있는 Left  Semi Join 예시이다.

select

       a.col_1, a.col_2

from tbl_a as a

       left semi join tbl_b as b on a.col_1 = b.col_1 and a.col_2 = b.col_2

 

하이브에서 세미 조인이 일반 내부 조인보다 효율적인 이유는 왼쪽 테이의 레코드에 대해서 오른쪽 테이블에서 일치하는 레코드를 찾으면 이상 일치하는 레코드를 찾지 않고 바로 데이터를 반환하고 멈추기 때문이다.

 

카테시안 프로덕트 조인(Cartesian Product Join) 조인의 왼쪽 테이블에 있는 튜플(tuple) 오른쪽에 있는 튜플이 모든 쌍을 맺는다. 다른 조인 유형과 달리 하이브에서는 카테시안 프로덕트를 병렬로 실행하지 않는다. 또한 맵리듀스에서 최적화되어 있지도 않다. 아래 스크립트는 하이브에서 전체 카테시안 프로덕트(Full Cartesian Product) 실행한다.

select

       a.*, b.*

from tbl_a as a

       join tbl_b as b

where a.col_1 = b.col_1

 

일반적인 RDBMS에서는 위와 같은 쿼리에 대해서 내부 조인에 최적화되어 있으나, 하이브에서 이런 종류의 쿼리는 WHERE 절을 적용하기 전에 전체 카테시안 프로덕트를 실행한다. 그래서 쿼리가 아주 오래 걸릴 있다. 사용자 부주의로 카테시안 프로덕트를 방지하기 위해 hive.mapred.mode 속성이 strict 되어 있으면 카테시안 프로덕트의 실행을 방지 있다.

 

 

2020-07-27 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, JOIN, HIVE LEFT SEMI JOIN, 하이브 최적화, 하이브 튜닝, Hive Tuning, Hive Query Hint, CartesianProductJoin, 카테시안조인

Hive JOIN 조인 최적화

 

·       Version : Hive

 

Hive RDBMS 같은 JOIN(조인) 구문을 제공하며 기능도 거의 유사하지만 동등조인(EQUI-JOIN) 제공한다.

 

내부조인(INNER JOIN) 경우 조인하는 모든 테이블에서 일치하는 레코드만 반환한다. ON 절은 테이블에서 조인할 레코드의 조건을명시한다.

select

       a.col_1, b.col_2

from tbl_a

       inner join tbl_b on a.col_1 = b.col_1

 

RDBMS 표준 SQL 경우 조인 키에 대해서 비동등 조인(NON-EQUI-JOIN) 허용하지만 하이브에서는 제공하지 않는다. 또한 하이브에서는 ON절에서 OR 조건의 사용을 허용하지 않는다. 만약 ON 절에 OR 사용하려고 한다면 아래 스크립트와 같이 UNION ALL으로 쿼리를 풀어서 사용할 있다.

select

       *

from test1 as t1

       join test2 as t2 on (t1.col1 = t2.col1 and t1.col1 = 1) or (t1.col1 = t2.col2 and t1.col1 = 2);

 

/* OR 대신 UNION ALL 사용 */

select

       *

from test1 as t1

       join test2 as t2 on (t1.col1 = t2.col1 and t1.col1 = 1)

 

union all

 

select

       *

from test1 as t1

       join test2 as t2  on (t1.col1 = t2.col2 and t1.col1 = 2);

 

 

대부분의 하이브는 조인할 각각의 쌍에 대해서 별도의 맵리듀스 잡을 사용한다. 또한 하이브는 왼쪽에서 오른쪽으로 쿼리를 처리하며 조인 순서 또한 왼쪽에서 오른쪽(from 순서)으로 처리한다. 3 이상의 테이블을 조인할 , 모든 ON 절에서 같은 조인키를 사용한다면 하나의 맵리듀스 잡을 사용한다.

 

하이브에서 조인을 처리할때, 마지막 테이블을 가장 크다고 가정한다. 다른 테이블을 버퍼링하려고 시도하고, 레코드에 대해서 조인을 수행하면서 마지막 테이블을 흘려보낸다. 그러므로 조인쿼리를 구성할때, 가장 테이블을 가장 마지막에 위치하도록 해야한다. 가장 테이블을 쿼리의 마지막에 위치하지 못하였더라도 힌트를 사용하면 마지막에 처리할 있다. 아래 스크립트는 힌트를 사용하여 from 테이블을 마지막에 처리할 있도록 한다.

SELECT

       /*+ STREAMTABLE(s) */ s.*, b.*

from tbl_s   

       inner join tbl_b ON s.col_1 = b.col_1

where s.col_1 = ?

 

 

데이터 조회시 검색 최적화를 위해 파티션 필터를 사용하는데 OUTER JOIN (외부조인) 경우 파티션 필터를 무시한다. 하지만 내부 조인의 ON절에 파티션 필터를 사용하면 동작한다. 따라서 모든 조인에서 파티션 필터를 사용하기 위해 중첩 SELECT 사용하여 해결할 있다.

select

       a.col_1, b.col_1

from (select * from tbl_a where partition_filter = ? and col_1 = ?) as a

       left outer join (select * from tbl_b where partition_filter = ? and col_1 = ?) as b on a.col_1 = b.col_1

 

중첩 SELECT 문은 데이터 조인 전에 파티션 필더를 적용하는데 필요한 푸시다운(push down) 수행한다. 하이브는 조인을 수행한 후에 WHERE 절을 평가한다. 따라서 WHERE 절은 NULL 되지 않는 컬럼값에 대해서만 필터를 적용할 있도록 해야한다.

 

 

2020-07-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, JOIN, INNER JOIN, 하이브 최적화, 하이브 튜닝, Hive Tuning, Hive Query Hint

Hive LIKE RLIKE

 

·       Version : Hive

 

Hive에서 LIKE 구문은 RDBMS LIKE 구문과 동일한 동작으로, 어떤 서브 문자열(substring) 문자열의 시작이나 , 혹은 문자열 내에서 일치하는지 확인할 있다.

 

아래 스크립트는 LIKE 구문으로 검색한 것이며, OR 절을 사용하여 여러개의 LIKE 구문을 사용하였다.

DROP TABLE IF EXISTS TBL_A;

CREATE TABLE TBL_A(

COL_1 STRING

);

 

INSERT INTO TBL_A(COL_1) VALUES ('CHICAGO'), ('NEWYORK');

 

SELECT * FROM TBL_A WHERE COL_1 LIKE '%CA%' OR COL_1 LIKE '%YO%';

 

 

 

하이브는 LIKE 절을 자바 정규표현식으로 사용할 있는 RLIKE 절로 확장하여 LIKE 조합으로 검색하기 어려운 문자열을 표현할 있다. 아래 스크립트는 RLIKE 예제이다.

select * from tbl_a where col_1 RLIKE '.*(ca|Yo).*';

 

 

예제에서 마침표(.) 어떤 문자와 일치하고 (*) 왼쪽에 있는 것이 0번에서 여러 반복되는 것을 의미한다. 따라서 , 뒤에서 마침표가 반복된다. (x|y)  표현식은 x또는  y 문자열이 일치하는 것을 의미한다.

 

2020-07-21 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, Hive SQL, LIKE, RLIKE

HDFS fsimage 에디트 로그

 

·       Version : HDFS

 

HDFS 에서 클라이언트가 파일을 생성하거나 이동할때 에디트 로그에 먼저 기록한다. 네임노드는 파일시스템 메타데이터를 메모리로 로드하여 -메모리 자료구조로 관리하며 에디트 로그가 수정된 업데이트를 진행한다. -메모리 메타데이터는 읽기 요청을 수행하는데 사용되며 디렉터리에 쓰기 동작이 끝나고 나서 성공했다는 결과가 클라이언트로 반환 되기전에 에디트 로그를 플러시하여 동기화한다. 이렇게 함으로서 장애가 발생해도 데이터 유실을 방지할 있다.

 

fsimage 파일시스템 데이터의 영속적인 체크포인트 파일이다. 하지만 개별 쓰기 동작 때마다 갱신되지는 않는다. fsimage 파일 시스템에서 존재하는 모든 디렉터리와 파일 아이노드(inode) 정보를 바이트로 직렬화 한다. 아이노드는 파일의 복제 단위, 변경 접근시간, 접근권한, 블록 크기와 파일을 구성하는 블록 조합들 같은 정보를 가진다. 디렉터리는 변경 시간, 권한 할당, 크기 같은 메타데이터가 저장된다. fsimage 파일은 블록이 저장되는 데이터노드 정보를 기록하지는 않는다. 대신 네임노드는 메모리상에 블록과 데이터 노드 매핑정보를 유지한다. 네임노드는 데이터 노드가 클러스터에 참여할 블록 리스트를 요청하여 매핑정보를 구성하며 주기적으로 정보를 받아 매핑정보를 최신상태로 유지한다.

 

에디트 파일은 크기 제한없이 증가할 있다. 네임노드가 구동 중일 때에는 에디트 파일이 커지더라도 특별한 영향을 주지는 않지만 네임노드가 재시작될 경우, 많은 에디트 로그의 개별 동작들을 메모리에 반영하기 위해 상당한 시간이 소요된다. 시간 동안은 파일 시스템을 사용하지 못하는 상황이 발생한다. 이와 같은 문제를 방지하기 위해 보조 네임노드를 구성한다. 보조 네임노드는 네임노드의 -메모리 메타데이터에 체크포인트를 생성하는 것이다. 체크포인트는 아래와 같은 순서로 진행된다.

1.       보조 네임노드는 네임노드에 edits 파일을 순환 사용하도록 요청하고 네임 노드에서 새로운 edits 로그는 새로운 파일에 저장된다.

2.       보노 네임노드는 HTTP GET 이용해서 네임노드의 fsimage edits 가져온다.

3.       보조 네임노드는 fsimage 메모리에 로드하고 edits 동작을 반영한다. 그리고 나서 새롭게 통합된 fsimage 파일을 생성한다.

4.       보조 네임노드는 HTTP POST 이용하여 새로운 fsimage 파일을 네임노드에 전송한다.

5.       네임노드는 이전 fsimage 보조 네임노드로부터 받은 새로운 이미지로 교체하며, 이전 edits 파일을 1단계에서 시작한 새로운 edits 교체한다. fsimage 파일도 체크포인트가 발생한 시간을 기록하기 위해 변경된다.

 

아래 그림은 체크포인트 과정을 이해하기 쉽도록 그림으로 표현한 것이다.

 

 

2020-07-14 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, edit log, fsimage, 체크포인트, checkpoint, namenode, 네임노드

Hive 무조건 MapReduce 사용할까

 

·       Version : Hive

 

Hive에서 쿼리를 실행할때, 무조건 맵리듀스(MapReduce) 사용할까?  하이브에서 대부분의 쿼리를 실행할 경우 맵리듀스가 사용된다. 하지만 일부 쿼리의 경우 로컬 모드 환경에서 맵리듀스를 사용하지 않고도 쿼리가 동작 할수도 있다. 예를 들어 아래 스크립트 처럼 단순히 테이블을 조회하는 쿼리는 맵리듀스를 사용하지 않는다.

select * from tbl_a;

 

단순히 SELECT 같은 쿼리는 하이브가 테이블로 부터 레코드를 읽고 형식에 맞춰서 콘솔로 출력한다. 경우 맵리듀스 작업대신 파일에서 Fetch Task 전체 데이터를 가져온다. 마치 아래 하둡 명령과 유사하다.

hadoop fs -cat $ file_name

 

일반적으로 min / max / count 같은 모든 종류의 집계에는 맵리듀스 작업이 필요하다.  또한 컬럼을 사용하게 되면 하이브는 파일에서 구문을 분석하여 행에서 컬럼을 추출해야 하므로 맵리듀스 작업이 필요하다.

 

hive.exec.mode.local.auto 속성을 true 설정하면 다른 연산도 로컬 모드로 실행을 시도한다.

hive.exec.mode.local.auto = true;

 

 

 

 

2020-07-14 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브 테이블, Hive table, 하이브쿼리, Hive SQL, 맵리듀스, MapReduce

Hive에서 SELECT 결과를 테이블로 INSERT 하기

 

·       Version : Hive

 

Hive에서 쿼리 결과를 테이블에 입력할때, 이미 존재하는 테이블에 데이터를 입력할수도 있으며, 새로운 테이블을 생성하며 데이터를 입력할 수도 있다. 이미 존재하는 테이블에 SELECT 결과를 저장할 때는 INSERT 구문을 사용한다. OVERWRITE 예약어를 사용하여 해당 파티션의 데이터를 교체할 있다. OVERWRITE 예약어를 INTO 변경하면 하이브는 데이터를 교체하지 않고 원래 데이터에 추가한다.

INSERT OVERWRITE TABLE tbl_new PARTITION (month = '1', day = '1')

select * from tbl_origin as origin

where origin.month = '1' and origin.day = '1';

 

만약 여러 파티션 데이터를 만들때, 파티션별로 INSERT 구문을 만들면 반복해서 데이터를 읽어야 하는 비효율적인 부분이 발생한다. 하이브는 입력 데이터를 한번 읽어서 이를 다수의 테이블로 분산하는 문법을 제공한다.

from tbl_origin as origin

INSERT OVERWRITE TABLE tbl_new PARTITION (month = '1', day = '1')

       select * where origin.month = '1' and origin.day = '1'

INSERT OVERWRITE TABLE tbl_new PARTITION (month = '2', day = '1')

       select * where origin.month = '2' and origin.day = '1'

INSERT OVERWRITE TABLE tbl_new PARTITION (month = '3', day = '1')

       select * where origin.month = '3' and origin.day = '1';

 

 

SELECT 결과물을 새로운 테이블을 생성하면서 저장하는 방법은 CREATE 구문을 사용할 있다.

CREATE TABLE tbl_create

AS SELECT col1, col2, col3

from tbl_origin

where month = '1' and day = '1';

 

 

 

2020-07-13 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브 테이블, Hive table, 하이브쿼리, Hive SQL, 데이터 저장, INSERT SELECT

Hive 테이블 삭제, 수정

 

·       Version : Hive

 

하이브에서 테이블을 삭제하는 명령은 DROP TABLE 명령어를 사용한다.

DROP TABLE IF EXISTS table_name;

 

테이블을 삭제할때, 하둡의 휴지통기능이 활성화되어 있으면 데이터는 분산 파일 시스템의 .Trash 디렉터리로 이동된다. 휴지통 기능에 설정된 시간이후 데이터가 완전히 삭제 된다. 휴지통 기능이 비활성화 되어 있는 경우 즉시 삭제된다. 또한 삭제하려는 테이블이 외부 테이블인경우, 테이블의 메타데이터만 삭제되며 데이터는 그대로 남아있다.

 

테이블 수정은 ALTER TABLE 명령을 사용하여 변경한다. 테이블 수정은 메타데이터만 변경할 데이터 자체는 변경시키지 않는다.

[테이블명 변경]

Table_name 테이블명을 table_name_new 테이블명으로 변경한다.

ALTER TABLE table_name TO table_name_new

 

[파티션 추가/변경/삭제]

파티션 추가는 ADD PARTITION 명령을 사용한다.

ALTER TABLE table_name ADD IF NOT EXISTS

PARTITION(year = 2020, month = 1, day = 1) LOCATION '/user/data/20200101'

PARTITION(year = 2020, month = 1, day = 2) LOCATION '/user/data/20200102'

PARTITION(year = 2020, month = 1, day = 3) LOCATION '/user/data/20200103';

 

파티션 위치 변경은 SET LOCATION 명령을 사용한다.

ALTER TABLE table_name PARTIOTN(year = 2020, month = 1, day = 1)

SET LOCATION '/user/data/…';

 

파티션 삭제는 DROP PARTITION 명령을 사용한다.

ALTER TABEL table_name DROP IF EXISTS PARTITION (year = 2020, month = 1, day = 1);

 

 

[컬럼 변경]

컬럼명, 컬럼 위치, 주석 데이터 타입을 변경할 있다. old_column 컬럼명을 new_column 이름으로 변경하고 데이터 타입은 INT, 컬럼의 위치는 col2 뒤에 위치한다.

ALTER TABLE table_name

CHANGE COLUMN old_column new_column INT

COMMENT 'Input comment'

AFTER col2;

 

컬럼 이름이나 데이터 타입을 변경하지 않더라도, 컬럼의 예전이름과 새이름, 데이터 타입을 지정해야 한다.컬럼을 이동하지 않는다면 AFTER 명령은 필요하지 않으며, 컬럼을 앞으로 위치할 경우 FIRST 사용할 있다.

 

[컬럼 추가 / 삭제   교체]

컬럼 추가는 이미 존재하는 컬럼의 마지막과 파티셔닝 컬럼 앞에 추가된다.

ALTER TABLE table_name ADD COLUMNS (

add_col1 STRING COMMENT 'Input Comments',

add_cpl2 LONG COMMENT 'Input Comments');

 

이미 존재하는 모든 컬럼을 삭제하고 새로운 컬럼으로 교체한다. 메타 데이터만 변경된다.

ALTER TABLE table_name REPLACE COLUMNS(

col1 INT COMMENT 'Input Comments',

col2 STRING COMMENT 'Input Comments',

col3 LONG COMMENT 'Input Comments');

 

 

 

 

2020-07-07 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브 테이블, Hive table, 하이브쿼리, Hive SQL, 하이브파티션, 테이블삭제, 테이블수정

Hive 파티션 테이블에서 where  없는 쿼리 실행 방지

 

·       Version : Hive

 

하이브에서 테이블 파티셔닝을 하는 가장 이유는 빠르게 데이터를 검색하기 위해서이다. 아주 데이터가 있더라도 파티션 스키마가 검색하려는 범위 필터링을 반영한다면 파티셔닝 테이블은 쿼리의 성능을 극적으로 올려준다. 그래서 특정값을 필터하는 WHERE 절에 파티션 조건을 포함하는데 이러한 조건을 파티션 필터라고 부른다.

그러나 파티셔닝이 되어 있다고 하더라도, 테이블 데이터가 많거나 파티션 개수가 많다면 거대한 맵리듀스 작업을 유발할 있다. 이러한 맵리듀스의 부하를 방지하기 위해 WHERE 절에  파티션 필터가 없는경우 쿼리 실행이 되지 않도록 옵션을 설정할 있다.

 

아래 스크립트는 WHERE절에 파티션 필터가 없는경우 쿼리가 실행되지 않도록 적용한 예시이다.

hive> set hive.mapred.mode = strict;

hive> select * from campaign;

FAILED: SemanticException [Error 10056]: Queries against partitioned tables without a partition filter are disabled for safety reasons. If you know what you are doing, please set hive.strict.checks.no.partition.filter to false and make sure that hive.mapred.mode is not set to 'strict' to proceed. Note that you may get errors or incorrect results if you make a mistake while using some of the unsafe features. No partition predicate for Alias "campaign" Table "campaign"

hive>

 

 

 

아래 스크립트는 WHERE 절에 파티션 필터가 없을 경우에도 쿼리가 실행된다.

hive> set hive.mapred.mode = nonstrict;

hive> select * from campaign;

OK

Time taken: 0.671 seconds

hive>

 

현재 테이블에 생성되어 있는 파티션키 정보를 확인하려면 아래 명령을 실행한다.

hive> show partitions campaign;

OK

date_local=20200616

date_local=20200617

date_local=20200630

Time taken: 0.13 seconds, Fetched: 3 row(s)

hive>

 

 

 

 

2020-07-01 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브 테이블, Hive table, 하이브쿼리, Hive SQL, 하이브파티션, 파티션필터, partition filter

Hive 매니지드 테이블 외부 테이블

 

·       Version : Hive

 

하이브에는 매니지드 테이블과 외부 테이블이라고 불리는 테이블 저장 방식이 있다. 둘의 차이점은 데이터 소유자가 하이브이냐, 아니냐로 크게 구분할 있다.

 

매지니드 테이블 (Managed Table) 내부 테이블이라고도 불리며 하이브 속성(hive.metastore.warehouse.dir)에서 정의한 디렉터리의 하위 디렉터리를 만들어서 데이터를 저장한다. 하이브에서 매니지드 테이블을 삭제할때 테이블내의 데이터가 삭제된다.

 

외부 테이블은 테이블을 생성할때, EXTERNAL 키워드를 사용하며, LOCATION절에서 지정한 위치에 데이터가 존재한다는것을 하이브에게 알려준다. 하이브에서 외부 테이블을 삭제하면, 하이브 내에서 스키마만 삭제될 데이터는그대로 존재한다. 그래서 중요한 데이터의 경우 실수를 방지하기 위해 외부 테이블로 만드는것을 권장한다.

 

테이블의 속성이 매니지드 또는 외부인지 확인할 있는 방법은 DESCRIBE EXTENDED 명령을 사용한다.

DESCRIBE EXTENDED 테이블명;

  

 

 

아래 스크립트는 매니지드 테이블처럼 스키마만 복사하여 외부 테이블로 생성한다.

create external table if not exists testdb.tbl_b

like testdb.tbl_a

location '/user/data/';

 

스키마를 복사하려는 원본 테이블이 외부 테이블인 경우 EXTERNAL 명령을 생략하여도 외부 테이블로 생성된다.

 

 

 

2020-06-24 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브 테이블, Hive table, 하이브쿼리, Hive SQL

HDFS 저장소에 데이터를 압축해서 저장하면 좋을까?

 

·       Version : HDFS

 

HDFS 클러스터에서 데이터를 저장할때, 압축을 해서 보관하는것이 좋을까? 그냥 저장하는 것이 좋을까? 결론부터 말하면 반은 맞고 반은 틀리다. , 압축의 특성을 이해하고 사용하면 좋지만, 그렇지 못할경우 오히려 HDFS 장점을 활용하지 못할 수도 있다.

 

맵리듀스가 처리할 데이터를 압축하는 방법을 고려할때, 압축 포맷이 분할을 지원하는지 여부를 이해하는것이 중요하다. 예를들어 HDFS 1GB 데이터 파일을 저장한다고 가정한다.  64MB 블록으로 처리할 경우 16개의 블록으로 나뉘어 HDFS 저장된다. 리듀스에서 파일을 입력 데이터로 사용할 경우 16개의 독립적으로 처리되는 입력 분할을 생성할 것이다.

 

 

 

그런데 압축 크기가 1GB 하나의 gzip 압축 파일이 있다고 가정한다. 기존처럼 HDFS 16개의 블록에 저장할 것이다. 그러나 블록에 대한 분할 생성은 gzip 스트림이 특정 위치에서 읽기를 지원하지 않기 때문에 동작을 하지 않을것이다.  , 맵태스크가 나머지 블록의 분할을 개별적으로 읽는것은 불가능하므로 gzip 포맷을 저장하기 위해 DEFLATE 사용하고, DEFLATE 데이터를 일련의 압축된 블록으로 저장한다. 리더가 다음 블록의 시작으로 이동하려면 스트림과 동기화되어 스트림의 특정 지점에 있을 있는 어떤 방법을 지원해야 하는데, DEPLATE 압축 방식은 블록의 시작점을 구분할 없기 때문에  gzip 분할을 지원하지 않는다. 그래서 맵리듀스는 gzip 분할을 지원하지 않는다는 것을 인식하고, 파일을 분할하려고 하지 않을것이다. 그러면 단일 지역으로 데이터가 편향되어 지역성 비용이 증가하게 된다. , 단일 맵이 16개의 HDFS 블록을 처리할 것이고, 블록은 대부분 맵의 로컬에 있지 않을 가능성이 크다. 소수의 맵과 함께 잡은 일반적인 잡보다 세분화 되지 않아 오랫동안 수행될 확률이 크다.

 

압축파일이 bzip2 어떨까? bzip2 파일은 블록 사이에서 동기화 표시가를 제공(파이의 48비트 근사치)하고 결과적으로 분할을 지원한다.

 

ZIP파일은 아카이브 포맷이기 때문에 다중 파일을 단일 ZIP 아카이브로 결합시킬 있다. 파일은 개별적으로 압축되고 아카이브에 있는 모든 파일 위치는 ZIP 파일의 끝에서 중앙 디렉터리에 저장된다. 이러한 속성은 ZIP 파일이 파일 단위로 분할을 지원한다는 것을 의미한다. 그리고 분할은 ZIP 아카이브로부터 하나 이상의 파일들을 포함한다. (zip 지원 여부는 확인이 필요하다.)

 

LZO 파일의 경우 기존의 압축 포맷의 리더가 스트림과 동기화되는 방법을 제공하지 않기 때문에 분할이 불가능하다.

 

아래표는 하둡에서 지원하는 압축 분할 여부이다.

Compression format

Tool

Algorithm

File extention

Splittable

gzip

gzip

DEFLATE

.gz

No

bzip2

bizp2

bzip2

.bz2

Yes

LZO

lzop

LZO

.lzo

Yes if indexed

Snappy

N/A

Snappy

.snappy

No

 

외에도 시퀀스 파일을 사용하거나,  청크 단위로 파일을 나누어서(이때 청크는 HDFS 블록 하나 정도 크기로 생성한다.) 개별적으로 압축을 하여 사용하면 압축 파일 분할 여부와 관계없이 어느정도 효율성을 발휘할 있다.  

 

 

[참고자료]

·       Choosing a Data Compression Format : https://docs.cloudera.com/documentation/enterprise/5-3-x/topics/admin_data_compression_performance.html

·       Data Compression in Hadoop : http://comphadoop.weebly.com/

 

 

 

2020-06-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, 하둡 파일 압축, 분산 처리, 분산 저장

Hive 테이블

 

·       Version : Hive

 

하이브에서 테이블을 생성 할때에는 SQL 규칙을 따르지만 테이블의 데이터 파일 생성 위치나 사용할 포맷등 확장기능을 사용하여 유연성을 제공한다.

CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name    -- (Note: TEMPORARY available in Hive 0.14.0 and later)

  [(col_name data_type [column_constraint_specification] [COMMENT col_comment], ... [constraint_specification])]

  [COMMENT table_comment]

  [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]

  [CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]

  [SKEWED BY (col_name, col_name, ...)                  -- (Note: Available in Hive 0.10.0 and later)]

     ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)

     [STORED AS DIRECTORIES]

  [

   [ROW FORMAT row_format]

   [STORED AS file_format]

     | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)]  -- (Note: Available in Hive 0.6.0 and later)

  ]

  [LOCATION hdfs_path]

  [TBLPROPERTIES (property_name=property_value, ...)]   -- (Note: Available in Hive 0.6.0 and later)

  [AS select_statement];   -- (Note: Available in Hive 0.5.0 and later; not supported for external tables)

 

“IF NOT EXISTS” 명령은 테이블의 존재 유무를 확인하여, 테이블이 없을 경우 명령을 실행한다. 명령을 사용하면, 동일한 이름의 테이블이 있을경우 에러를 발생시키지 않고 다음 단계로 진행 있다. 하지만 이름만 확인할 스키마 구조까지 확인하는것은 아니다.

 

아래 스크립트는 Hive에서 테이블의 데이터를 제외한 스키마만 복사한다.

CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name

  LIKE existing_table_or_view_name

[LOCATION hdfs_path];

 

ex) CREATE TABLE IF NOT EXISTS testdb.mytable2 LIKE testdb.mytable;

 

테이블 정보를 확인하기 위해서는 DESCRIBE 명령을 사용한다.

describe tlb_a;

 

 

테이블의 정보를 자세히 확인할 때에는 EXTENDED 명령을 추가한다. EXTENDED 사용할 경우 자세한 정보가 출력되지만, 사람이 읽기에는 줄바꿈 등이 되지 않아 가독성이 불편하다.

describe extended tlb_a;

 

 

 

EXTENDED 대신 FROMATTED 사용하면 줄바꿈등이 적용되어 가독성이 뛰어나다.

describe formatted tlb_a;

 

 

EXTENDED 옵션을 사용한 출력에서 location 항목은 테이블의 데이터를 저장하는 HDFS 디렉터리 전체 URI 경로를 보여준다.

 

 

[참고자료]

 

 

 

2020-06-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브 테이블, Hive table, 하이브쿼리, Hive SQL

 

HiveQL Hive 데이터베이스

 

·       Version : Hive

 

HiveQL Hive에서 사용하는 쿼리 언어이다. SQL 유사하지만 SQL 다르며 표준 ANSI SQL 지원하지 않는다. 하이브는 로우(ROW) 레벨의 삽입과 변경, 삭제를 지원하지 않으며, 트랜잭션 또한 지원하지 않는다. 하지만 하둡이 지원하는 범위 안에서 성능 확장을 위해 다양한 기능을 제공하며, 사용자가 정의한 확장과 외부 프로그램을 하이브와 연동할 수도 있다.

 

하이브에서 데이터베이스 개념은 단지 테이블의 카탈로그 또는 네임스페이스이다. 데이터베이스는 논리적인 그룹을 구성할 있으며 대규모 작업시 동일한 테이블명의 충돌을 방지할수도 있다. 데이터베이스를 별도로 지정하지 않으면 기본 데이터베이스(default) 사용한다. 아래 스크립트는 데이터베이스를 생성한다.

create database testdb;

 

create database if not exists testdb;

  

하이브는 데이터베이스마다 별도의 디렉터리를 생성하고 테이블을 하위 디렉터리에 저장한다. 데이터베이스 디렉터리는 “hive.metastore.warehouse.dir” 속성에 설정한 최상위 디렉터리 밑에 생성된다.  아래 스크립트는 데이터베이스 생성시 디렉터리 위치를 변경할 있다.

create database testdb

location '/user/data/testdb';

 

현재 생성되어 있는 데이터베이스의 디렉터리 경로를 확인하려면 describe 명령을 사용한다.

describe testdb;

 

데이터베이스 삭제 명령은 drop 명령을 사용한다. 하이브는 가본적으로 테이블이 있는 데이터베이스를 삭제하는것을 허용하지 않는다. 테이블을 모두 삭제 데이터베이스를 삭제 또는 cascade 명령을 사용하여 테이블이 존재하는 데이터베이스를 삭제할 있다. 데이터베이스가 삭제되면 해당 디렉터리도 같이 삭제 된다.

drop database if exists testdb cascade;

 

 

 

2020-06-16 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브 데이터베이스, HiveQL, 하이브쿼리

'SW Engineering > Hadoop' 카테고리의 다른 글

HDFS 저장소에 데이터를 압축해서 저장하면 더 좋을까?  (0) 2020.06.23
Hive 테이블  (0) 2020.06.23
Hive 텍스트파일 인코딩  (0) 2020.06.12
Impala Connection refuse Error  (0) 2020.06.12
Hive 데이터 타입  (0) 2020.06.09

Hive 텍스트파일 인코딩

 

·       Version : Hive

 

텍스트 데이터의 필드를 구분할때, (TAB) 또는 콤마(,) 많이 사용한다. 이러한 일반적인 구분 기호는 데이터안에 콤마나 탭이 포함되어 있을 경우 전체 데이터 필드가 맞지 않는문제가 발생할 있어 주의해야 한다. 하이브도 또는 콤마 같은 필드 구분자를 지원하지만 앞에서 말한 이유 때문에 일반적으로 사용하지 않는 여러 제어 문자를 기본 구분 기호로 사용한다. 아래표는 하이브에서 제공하는 구분기호이다. 만약 필드에서 탭으로 분리하려면 ‘\t’ 사용하고, 콤마의 경우 ‘,’ 사용한다.

구분기호

설명

\n

레코드 바꿈

^A

모든 컬럼을 분리한다. CREATE TABLE 문에서 명시적으로 지정할때는 8진수 코드 ‘\001’ 사용한다.

^B

ARRAY, STRUCT, MAP Key-Value 요소를 분리한다. CREATE TABLE 문에서 명시적으로 지정할때는 8진수 코드 ‘\002’ 사용한다.

^C

MAP Key-Value 에서 키를 관련된 값과 분리한다. CREATE TABLE 문에서 명시적으로 지정할때는 8진수 코드 ‘\003’ 사용한다.

 

CREATE TABLE HIVE_TABLE (

       COL1 STRING,

       COL2 FLOAT,

       COL3 ARRAY<STRING>,

       COL4 MAP<STRING, FLOAT>,

       COL5 STRUCT<C_1:STRING, C_2:STRING, C_3:STRING, C_4:INT>

)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY '\001'

COLLECTION ITEMS TERMINATED BY '\002'

MAP KEYS TERMINATED BY '\003'

LINES TERMINATED BY '\n'

STORED AS TEXTFILE;

 

일반적으로 데이터베이스는 스키마 구조를 가지고 있으며, 데이터를 입력할때 스키마 구조에 맞춰서 입력한다. 이것을 ‘schema on write’라고 부른다. 하지만 하이브는 저장소에 대해 이런 쓰기 제어 구조를 가지고 있지 않으며 데이터를 읽을때 스키마를 적용한다. 이것을 ‘schema on read’라고 한다. 그래서 스키마와 파일의 내용이 일치하지 않으면 하이브는 값을 모두 null 채운다. 만약 숫자 필드가 정의되어있는데 문자열을 만나면 하이브는 null 반환한다.

 

 

 

2020-06-11 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브 텍스트파일 인코딩, 필드 구분, 문자열 구분

'SW Engineering > Hadoop' 카테고리의 다른 글

Hive 테이블  (0) 2020.06.23
HiveQL과 Hive 데이터베이스  (0) 2020.06.17
Impala Connection refuse Error  (0) 2020.06.12
Hive 데이터 타입  (0) 2020.06.09
HDFS 데이터 저장소에는 RAID구성이 필요할까  (0) 2020.06.08

+ Recent posts