PC에서 S3 파일 쿼리하기

PC에서 S3 파일 쿼리하기 (EC2, Hive, Hadoop 사용)

이 튜토리얼은 사용자의 PC에서 S3에 저장된 데이터를 Hive로 쿼리하는 방법을 보여줘요. EC2에서 프로비저닝한 컴퓨트 자원으로 쿼리를 실행하고, 오래 보관이 필요한 결과는 다시 S3에 저장하는 시나리오를 다룹니다.

출처: 문서

본문

사용 시나리오 (Usage Scenario)

  • 사용자는 S3에 데이터가 있습니다 (예: 클라우드에 보관된 Apache 로그 파일, S3로 백업된 데이터베이스).
  • 이 데이터셋 위에 테이블을 선언하고 SQL 쿼리를 실행하고 싶어요.
  • 이 SQL 쿼리는 EC2에서 프로비저닝한 컴퓨트 자원으로 실행되어야 합니다. 이상적으로 컴퓨트 자원은 쿼리의 컴퓨트 비용에 비례해 프로비저닝할 수 있어요.
  • 장기 보관이 필요한 쿼리 결과는 다시 S3에 저장할 수 있습니다.

필수 소프트웨어 (Required Software)

클라이언트 쪽(PC)에서 다음이 필요합니다.

  • HIVE-467을 포함한 어떤 Hive 버전 (현재 시점에 관련 패치는 커밋되지 않음. 편의상 이 패치가 적용된 Hive 배포판을 다운로드할 수 있음)
  • 패치가 적용된 Hadoop ec2 스크립트(src/contrib/ec2/bin) 버전. 이 스크립트는 EC2에서 hadoop 클러스터를 실행하는 데 사용돼요.
  • Hive는 로컬 Hadoop 디렉토리(HADOOP_HOME 환경 변수로 지정)를 요구합니다. EC2 클러스터에서 실행 중인 것과 호환되는 Hadoop 버전이면 돼요. branch-19에서 만든 hadoop 배포판으로 시도되었습니다.
  • 사용자가 이 시점에 Hive CLI(bin/hive)를 성공적으로 실행할 수 있다고 가정합니다.

Hive 설정 (Hive Setup)

모든 Hive 세션에 몇 가지 Hadoop 구성 변수가 필요해요. Hive CLI에서 다음과 같이 설정할 수 있습니다.

hive> set hadoop.socks.server=localhost:2600; 
hive> set hadoop.rpc.socket.factory.class.default=org.apache.hadoop.net.SocksSocketFactory;
hive> set hadoop.job.ugi=root,root;
hive> set mapred.map.tasks=40;
hive> set mapred.reduce.tasks=-1;
hive> set fs.s3n.awsSecretAccessKey=2GAHKWG3+1wxcqyhpj5b1Ggqc0TIxj21DKkidjfz
hive> set fs.s3n.awsAccessKeyId=1B5JYHPQCXW13GWKHAG2

s3n 키에 할당된 값은 예시일 뿐이며, 사용자가 자기 계정 정보에 맞게 채워야 해요. 나머지 값에 대한 설명은 아래 구성 가이드를 참고하세요.

CLI를 띄울 때마다 이 명령들을 지정하는 대신, Hive 설치의 conf/ 디렉토리에 있는 hive-site.xml에 지속적으로 저장할 수 있어요. 그러면 CLI가 실행될 때마다 그 값이 읽힙니다.

예시 공개 데이터셋 (Example Public Data Sets)

S3 버킷 data.s3ndemo.hive에 몇 가지 예시 데이터 파일이 제공됩니다. 튜토리얼의 SQL 예시에 사용할게요.

  • s3n://data.s3ndemo.hive/kv – 텍스트 파일의 키-값 쌍
  • s3n://data.s3ndemo.hive/pkv – 날짜별로 파티션된 디렉토리의 키-값 쌍
  • s3n://data.s3ndemo.hive/tpch/* – TPCH 벤치마크가 사용하는 8개 테이블에 해당하는 데이터를 담은 8개 디렉토리. 데이터는 TPCH가 제공하는 표준 dbgen 유틸리티로 scale 10(약 10GB) 데이터베이스에 대해 생성됩니다.

테이블 설정 (DDL 문)

이 예시에서는 HDFS를 Hive의 기본 테이블 저장소로 사용할 거예요. Hive의 외부 테이블(external tables) 기능을 사용해 S3의 파일 위에 Hive 테이블을 만들겠습니다. DDL 명령 실행에는 동작하는 Hadoop 클러스터가 필요하지 않아요 (메타데이터만 설정하기 때문).

키-값 쌍을 담은 간단한 테이블 선언:

hive> create external table kv (key int, values string) location 's3n://data.s3ndemo.hive/kv'; 

키-값 쌍을 담은 중첩 디렉토리 위에 파티션 테이블을 선언하고 테이블 파티션을 디렉토리와 연결:

hive> create external table pkv (key int, values string) partitioned by (insertdate string);
hive> alter table pkv add partition (insertdate='2008-01-01') location 's3n://data.s3ndemo.hive/pkv/2008-01-01';

TPCH 테이블 위에 테이블 선언:

hive> create external table lineitem (
l_orderkey int, l_partkey int, l_suppkey int, l_linenumber int, l_quantity double,
l_extendedprice double, l_discount double, l_tax double, l_returnflag string,
l_linestatus string, l_shipdate string, l_commitdate string, l_receiptdate string,
l_shipinstruct string, l_shipmode string, l_comment string)
row format delimited fields terminated by '|'
location 's3n://data.s3ndemo.hive/tpch/lineitem'; 

TPCH DDL 문은 원본 TPCH 문의 약간 수정된 버전이에요 (Hive가 TPCH의 모든 데이터 타입을 지원하지 않기 때문). Hive용 TPCH DDL 문은 모두 TpchDdlForHive.sql에서 찾을 수 있습니다.

쿼리 실행 (Executing Queries)

Hive는 Hadoop 클러스터 없이도 일부 쿼리를 실행할 수 있어요. 예:

hive> select * from kv limit 10; 

limit 절이 있는 select * 쿼리는 Hive CLI 자체에서 로컬로 수행할 수 있어요. 이렇게 할 때 주의할 점이 있습니다.

  • CLI가 동작하는 Hadoop 클러스터로 구성되지 않은 경우 fs.default.namefile:///로 설정해야 해요.
  • 대용량 데이터셋의 모든 행을 select하면 안 됩니다! 그러면 많은 양의 데이터가 S3에서 AWS 외부로 다운로드되어 호스트 계정에 비용이 발생해요!

물론 진짜 재미는 map-reduce로 비자명한(non-trivial) 쿼리를 하는 것이에요. 이를 위해 Hadoop 클러스터가 필요합니다.

  1. EC2에서 Hadoop 클러스터를 시작하세요 (Hadoop-EC2 튜토리얼 지침을 따르되, HADOOP-5839가 적용된 ec2 스크립트 버전을 사용할 것). 원하는 수의 노드를 할당할 수 있으며, 이 튜토리얼은 10개 노드로 시도되었습니다.
  2. 마스터 노드의 공개 호스트네임을 적어두세요. 예: ec2-12-34-56-78.compute-1.amazonaws.com
  3. 다음을 실행해 Hive CLI가 이 Hadoop 클러스터를 가리키도록 설정하세요.
  4. 포트 2600으로 Hadoop 마스터에 ssh 터널을 설정하세요 (다른 터미널/창에서 실행).
hive> set fs.default.name=hdfs://ec2-12-34-56-78.compute-1.amazonaws.com:50001;
hive> set mapred.job.tracker=ec2-12-34-56-78.compute-1.amazonaws.com:50002;
$ ssh -i <path to Hadoop private key path> -D 2600 ec2-12-34-56-78.compute-1.amazonaws.com

이제 준비가 끝났습니다. TPCH의 예시 쿼리(1.sql)를 다음과 같이 시도할 수 있어요.

hive> insert overwrite directory '/tmp/tpcresults-1.sql' 
  select l_returnflag, l_linestatus, sum ( l_quantity ) as sum_qty, sum ( l_extendedprice ) as sum_base_price,
  sum ( l_extendedprice * ( 1 - l_discount )) as sub_disc_price, 
  sum ( l_extendedprice * ( 1 - l_discount ) * ( 1 + l_tax )) as sum_charge,
  avg ( l_quantity ) as avg_qty, avg ( l_extendedprice ) as avg_price, 
  avg ( l_discount ) as avg_disc, count ( 1 ) as count_order
  from lineitem where l_shipdate <= to_date('1998-12-01') group by l_returnflag, l_linestatus; 

이것은 하나의 map-reduce 작업을 시작하며, 기본 hadoop/hive 설정의 10개 노드에서 약 10분이 걸렸습니다. 이 경우 결과는 HDFS에 저장되고, bin/hadoop 또는 hive CLI에서 dfs -cat /tmp/tpcresults/1-2.sql/*로 얻을 수 있어요. 위 쿼리는 Hive가 현재 구현하지 않는 order by 절을 생략했다는 점에서 TPCH 쿼리와 다릅니다.

결과를 S3에 다시 저장하기 (Storing results back in S3)

결과를 S3의 파일로 직접 저장할 수도 있어요. 예를 들어 이전 insert 절을 다음과 같이 바꿀 수 있습니다.

hive> insert overwrite directory 's3n://target-bucket/tpcresults-1.sql';

다른 방법으로 S3 위에 외부 테이블을 만들고 결과를 직접 저장할 수도 있어요. 예:

hive> create external table t1 (flag string, status string, double ...)
  location 's3n://jssarma/tpcresults-1.sql';
hive> insert overwrite table t1 select ...;

마찬가지로 결과를 파티션된 외부 테이블의 파티션에 저장할 수도 있습니다.

HDFS의 임시 테이블 사용하기 (Using tmp tables in HDFS)

현재 Hive는 임시 테이블을 명시적으로 지원하지 않아요. 하지만 EC2의 HDFS에 정의된 테이블은 Hadoop 클러스터 수명 동안만 존재하므로 임시 테이블과 같습니다. S3에 직접 접근하는 것보다 훨씬 빠를 수 있으므로, 세션 중에 반복 접근하는 데이터를 스테이징하는 데 사용할 수 있어요.

예를 들어 TPCH 데이터셋에서 customer 속성과 order 세부 정보에 대한 분석을 하고 싶다면, 먼저 이 데이터셋들의 조인을 구체화(materialize)한 뒤 반복 쿼리를 하는 것이 유리합니다.

hive> create table cust_order (nationkey string, acctbal double, mktsegment string, orderstatus string, totalprice double);
hive> from customer c left outer join orders o on (c.c_custkey = o.o_custkey)
  insert overwrite table cust_order
  select c.c_nationkey, c.c_acctbal, c.c_mktsegment, o.o_orderstatus, o.o_totalprice;

부록: 구성 가이드 (Configuration Guide)

  • 소켓 관련 옵션은 Hive CLI가 (나중에 설정할) ssh 터널을 사용해 Hadoop 클러스터와 통신할 수 있게 해줘요.
  • job.ugi는 HDFS의 권한 문제를 피하기 위해 지정합니다.
  • mapred.map.tasks 지정은 HADOOP-5861을 우회하는 해킹이며, 큰 클러스터에서는 더 높게 설정해야 할 수 있어요.
  • mapred.reduce.tasks는 Hive가 reducer 수를 결정하도록 지정합니다 (HIVE-490 참고).

더 알아보기 (Learn more)

S3에 데이터를 두고 EC2 컴퓨트로 쿼리하는 이 방식은 데이터 레이크의 초기 형태예요. 외부 테이블 + 파티션 + ssh 터널 구성 흐름을 익히면 비용 효율적으로 대용량 데이터를 분석할 수 있습니다.