mysql의 경우 reserved word를 table의 컬럼명으로 쓰인다면 back quote(`)을 사용해야 한다.


https://dev.mysql.com/doc/refman/5.7/en/identifiers.html



The identifier quote character is the backtick (`):

mysql> SELECT * FROM `select` WHERE `select`.id > 100;




마찬가지로 hive에서도 reserved word를 table의 컬럼명으로 쓰인다면 back quote(`)을 사용해야 한다.



https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Select

 Any column name that is specified within backticks (`) is treated literally. 


hive> select * from googleplus_log where `date`='2037-08-23' and label='birthday' and `to`='11935385';

Posted by 김용환 '김용환'


json 데이터를 저장할 hive 테이블을 생성하는 예시이다. 

CREATE TABLE if not exists member

(

   name STRING,

   id INT, 

   props STRUCT <

       departname:STRING,

       alias:STRING

   >

) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'

STORED AS TEXTFILE





json 데이터를 hive에 저장할 때 개행 문자가 있으면 에러가 발생한다. 


$ cat "test.json"

{

  "name":"samuel",

  "id":1,

  "props": {

    "departname":"none",

    "alias":"kim"

  }

}


다음 에러로 발생한다. 

Failed with exception java.io.IOException:org.apache.hadoop.hive.serde2.SerDeException: Row is not a valid JSON Object - JSONException: A JSONObject text must end with '}' at 2 [character 3 line 1]


따라서 개행 문자 없이 사용해야 한다. 


$ cat "test.json"

{  "name":"samuel",  "id":1,  "props":{    "departname":"none",    "alias":"kim"  }}






이제 하둡에 json 파일을 업로드한다.


$ hadoop fs -put test.json /lib/test.json


hive 실행을 실행해서 데이터를 읽게 한다.



hive> LOAD DATA INPATH '/lib/test.json' OVERWRITE INTO TABLE member;



hive> select * from member;

OK

samuel 1 {"departname":"none","alias":"kim"}

Time taken: 0.614 seconds, Fetched: 1 row(s)


SELECT props.alias FROM member WHERE props.departname="none";

kim



Posted by 김용환 '김용환'



hive에서 json 컬럼에 대해서 json 쿼리를 진행할 수 있다. 



hive> select * from googleplus_log where date_id='2037-08-23' and label='birthday' and get_json_object(props, '$.id')='11935385';




json_tuple도 사용할 수 있지만, lateral view도 써야 하고 parittion table이라면 strict 모드로 바꾸라 한다. 


hive> select log.date_id, b.* from googleplus_log log lateral view json_tuple(log.props, 'result', 'birth', 'id', 'action') b where date_id='2017-02-23' and label='birthday'; 


This happens cos the hive is set to strict mode. this allow the partition table to access the respective partition /folder in hdfs .



hive>  set hive.mapred.mode=unstrict; 


hive> select log.date_id, b.* from googleplus_log log lateral view json_tuple(log.props, 'result', 'birth', 'id', 'action') b where date_id='2017-02-23' and label='birthday'; 

##잘 동작한다.






Posted by 김용환 '김용환'


Hive - get_json_object 호출시 에러 


hive에서 hive udf의 json을 사용하려 할 때(get_json_object를 사용, ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'를 사용) 다음 에러가 발생한다. 


Error while compiling statement: FAILED: RuntimeException MetaException(message:java.lang.ClassNotFoundException Class org.openx.data.jsonserde.JsonSerDe not found)
class org.apache.hive.service.cli.HiveSQLException



에러가 발생하지 않고 정상적으로 실행하려면,다음과 같이 실행하면 get_json_object가 실행된다.

$ wget http://www.congiu.net/hive-json-serde/1.3.7/cdh5/json-serde-1.3.7-jar-with-dependencies.jar
$ hive
hive> add jar /위치/json-serde-1.3.7-jar-with-dependencies.jar


세션이 실행될 때마다 동작시키려면 .hiverc를 수정한다.


$ vi ~/.hiverc

..

add jar /위치/json-serde-1.3.7-jar-with-dependencies.jar











Posted by 김용환 '김용환'





hive 쿼리를 실행 중에 예약어를 쓰면 에러가 발생할 수 있다. 



FAILED: ParseException line 1:85 Failed to recognize predicate 'to'. Failed rule: 'identifier' in table or column identifier



이럴 때는 두 가지 방법으로 문제를 해결할 수 있다. 


1번째 방법이다. 


SET hive.support.sql11.reserved.keywords=false;

select * from src.google_plus_log where date_id='2037-02-22' and to='365600561231231123121212'


2번째 방법은 back quote를 사용한다.


select * from src.google_plus_log where date_id='2037-02-22' and `to`='365600561231231123121212'


Posted by 김용환 '김용환'



hadoop ls는 명령어가 많지 않다. 


d h R 밖에 없다. 


Usage: hadoop fs [generic options] -ls [-d] [-h] [-R] [<path> ...]



그래서 먼가 후처리를 하고 싶다면, 파이프라인을 활용해야 한다.


예를 들어, 특정 디렉토리에 최근에 만들어진 파일을 얻고 싶다면 다음과 같이 모든 파일을 출력하게 한 후, 시간으로 리버스한 후, 마지막 하나를 읽어오면 된다. 


이 명령어로 검증해보고..


$ hadoop fs -ls -R  /google/app-store-log/  | sort -k 6 | tail -n 1



아래 명령어를 쓰면 최근에 생성된 파일을 찾을 수 있다.


hadoop fs -ls -R /google/app-store-log/  | sort -k 6 | tail -n 1 | awk '{print $8'}



특정 디렉토리의 최신 파일을 복사하려면, 다음과 같이 하면 된다. 



hdfs dfs -get `hadoop fs -ls -R  /google/app-store-log/ | sort -k 6 | tail -n 1 | awk '{print $8'}` /tmp/google-spark-job.jar


Posted by 김용환 '김용환'

hadoop client 설치 URL

hadoop 2016.10.24 19:11



cloudera 5.5.1의 hadoop 2.6.0 버전을 설치하고 싶다면, 아래 싸이트에 접속해서

hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64.rpm를 다운로드한 후 설치한다. 



https://archive.cloudera.com/cdh5/redhat/6/x86_64/cdh/5.5.1/RPMS/x86_64/ 





막상 설치하려면, 아래와 같은 에러가 발생한다. 



경고: hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID e8f86acd: NOKEY

오류: Failed dependencies:

bigtop-utils >= 0.7 is needed by hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64

zookeeper >= 3.4.0 is needed by hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64

avro-libs is needed by hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64

parquet is needed by hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64



따라서, RPM을 따라하면 엄청 쉽지 않은 작업이 계속 연결되어 있다 .


한번 제대로 설치한 후, 꼭 tar.gz으로 묶어 들고 공유 디렉토리에 잘 저장해 두어야 한다.. 


Posted by 김용환 '김용환'


hive 버전을 알려면, 다음과 같이 실행한다.



$ hive --version


Hive 1.1.0-cdh5.5.1



또는 libary 명으로 확인한다.


$ ls -al /usr/lib/hive/lib/hive*






hadoop 버전을 알려면, 다음과 같이 실행한다.



$ hadoop version


Hadoop 2.6.0-cdh5.5.1







Posted by 김용환 '김용환'


다음 그림은 파티션 범위를 이해하게 하는 그림으로서 전체 윈도우 표현식이다.





* current row : 현재 로우


* X PRECEDING 또는 Y FOLLOWING : 현재 로우(currow row)의 앞/뒤로 N 개의 로우를 의미한다.


* UNBOUNDED PRECEDING : 시작 지점을 알리며, 해당 윈도우는 파티션의 1 번째 로우이다.


* UNBOUNDED FOLLOWING : 마지막 지점을 알린다. 해당 윈도우는 파티션의 마지막 로우이다.


UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING: 테이블의 모든 로우를 의미하며, 1 번째와 마지막 로우를 각각 가르킨다.


* BETWEEN … AND : 윈도우의 시작 지점과 마지막 지점을 명세하기 위해 BETWEEN...AND 절을 사용한다. AND 앞의 표현식은 시작 지점을 정의하고, AND 뒤의 표현식은 마지막 지점을 정의한다. ROWS N PRECEDING 또는 ROWS UNBOUNDED PRECEDING와 같이 BETWEEN...AND 절을 생략한다면, 하이브는 기본적으로 윈도우의 처음 또는 N 번째 앞 부분을 시작 지점으로, 현재 로우를 마지막 지점으로 간주한다.



Posted by 김용환 '김용환'




https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SortBy



하이브에서 사용되는 정렬 키워드를 소개한다.


* ORDER BY (ASC|DESC): RDMBS의 ORDER BY 문과 비슷하다. ORDER BY 문을 실행 시, 하나의 리듀서만 사용해 전역 정렬을 수행하면, 리턴 시간이 더 소요된다. ORDER BY 뒤에 LIMIT 사용하는 것을 강력 추천한다. 그래서, hive.mapred.mode = strict (hive.mapred.mode= nonstrict은 기본값이다.)로 설정하고 LIMIT을 명세하지 않으면, 에러가 발생한다. 



jdbc:hive2://> SELECT name FROM employee ORDER BY NAME DESC;

+----------+

|   name   |

+----------+

| Will     |

| Shelley  |

| Michael  |

| Lucy     |

+----------+



* SORT BY (ASC|DESC): 어떤 레코드의 컬럼으로 정렬할지 가리킨다. 데이터를 리듀서에 보내기 전에 정렬을 완료한다는 것을 의미한다. mapred.reduce.tasks=1을 설정하지 않는다면, SORT BY 문은 전역으로 정렬을 수행하지 않고, 각 리듀서에서 내부적으로 정렬된 데이터인지 확인한다. 이 경우에 ORDER BY 결과와 동일하다. 


--2 개의 리듀서를 사용하면 리듀서마다 정렬(sorting)하기 때문에 정렬 결과가 다르다.

jdbc:hive2://> SET mapred.reduce.tasks = 2;

No rows affected (0.001 seconds)


jdbc:hive2://> SELECT name FROM employee SORT BY NAME DESC;

+----------+

|   name   |

+----------+

| Shelley  |

| Michael  |

| Lucy     |

| Will     |

+----------+

4 rows selected (54.386 seconds)


--리듀서 한 개만 사용하면 order by 와 동일한 효과를 제공한다.

jdbc:hive2://> SET mapred.reduce.tasks = 1;

No rows affected (0.002 seconds)


jdbc:hive2://> SELECT name FROM employee SORT BY NAME DESC;

+----------+

|   name   |

+----------+

| Will     |

| Shelley  |

| Michael  |

| Lucy     |

+----------+

4 rows selected (46.03 seconds)



* DISTRIBUTE BY:  컬럼값이 일치하는 로우는 동일한 리듀서로 파티션 된다. 하나의 리듀서만 사용하면, 리듀스는 정렬된 입력을 보장하지 않는다. 매퍼 결과를 분배하기 위해 어느 리듀서로 결정할지 여부의 관점에서 보면, DISTRIBUTE BY는 RDBMS의 GROUP BY와 비슷하다. SORT BY를 사용할 때, SORT BY 앞에 DISTRIBUTE BY를 명세해야 한다. 그리고, 분배하기 위해 사용된 컬럼은 SELECT 뒤에 컬럼 이름이 나타나야 한다. 



- SQL의 GROUP BY와 같은 형태이기 때문에 select 뒤에 컬럼 이름이 나와야 한다.

jdbc:hive2://> SELECT name 

. . . . . . .> FROM employee_hr DISTRIBUTE BY employee_id; 

Error: Error while compiling statement: FAILED: SemanticException [Error 10004]: Line 1:44 Invalid table alias or column reference 'employee_id': (possible column names are: name) (state=42000,code=10004)


jdbc:hive2://> SELECT name, employee_id 

. . . . . . .> FROM employee_hr DISTRIBUTE BY employee_id; 

+----------+--------------+

|   name   | employee_id  |

+----------+--------------+

| Lucy     | 103          |

| Steven   | 102          |

| Will     | 101          |

| Michael  | 100          |

+----------+--------------+

4 rows selected (38.92 seconds)


--SORT BY로 사용하기 

jdbc:hive2://> SELECT name, employee_id  

. . . . . . .> FROM employee_hr 

. . . . . . .> DISTRIBUTE BY employee_id SORT BY name; 

+----------+--------------+

|   name   | employee_id  |

+----------+--------------+

| Lucy     | 103          |

| Michael  | 100          |

| Steven   | 102          |

| Will     | 101          |

+----------+--------------+

4 rows selected (38.01 seconds)



* CLUSTER BY: 동일한 그룹의 컬럼에 대해 DISTRIBUTE BY와 SORT BY 명령을 동시에 수행하는 명령어다. 그리고 내부적으로 각 리듀서에서 정렬된다. CLUSTER BY 문은 아직 ASC 또는 DESC를 지원하지 않는다. 전역으로 정렬되는 ORDER BY와 비교해, CLUSTER BY 명령은 각 분배된 그룹에서 정렬이 이루어진다. 전역 정렬을 실행할 때 사용할 수 있는 모든 리듀서를 작동시키려면, CLUSTER BY를 먼저 사용하고 뒤에 ORDER BY를 사용한다. 



jdbc:hive2://> SELECT name, employee_id 

. . . . . . .> FROM employee_hr CLUSTER BY name;  

+----------+--------------+

|   name   | employee_id  |

+----------+--------------+

| Lucy     | 103          |

| Michael  | 100          |

| Steven   | 102          |

| Will     | 101          |

+----------+--------------+

4 rows selected (39.791 seconds)



Posted by 김용환 '김용환'