2015년 4월 27일 월요일

SparkSQL cacheTable 메소드 사용 성능 비교 - default vs cacheTable vs cacheTable (with columnar Compression)


SparkSQL 을 사용하다 보면, 복잡한 Nested Query 를 사용하는 것보다, 최대한 쿼리들을 단순하게 쪼개고, 중간 결과물을 registerAsTable 로 Table 화 하여, 여러 Step 으로 나누어 하는 경우 훨씬 빠른 결과물을 얻을 수 있는 경우를 종종 접한다. 메모리 부족 에러 등도 이런경우 훨씬 덜하다.

그런데, 가끔 로그를 보다 보면, 앞부분에서 이미 수행했던 쿼리가 뒷부분에서 결과를 가지고 재 쿼리를 할때 앞에서 수행했던 쿼리를 다시 또 수행하는 현상을 목격한게 된다.

이런 경우를 막는 것이 cacheTable 메소드 인데... (sqlContext 안에 정의 되어 있음.) 메뉴얼에는 schemaRDD 의 경우 cache 메소드 보다 cacheTable 메소드를 강력히 추천한다고 되어 있다. (이유는 Columnar 압축 저장 방식 때문...)

RDD.cache() 처럼 이것도, 뒷부분에서 재사용이 많지 않을때는 약간의 overhead 만 더 주어 좀더 느려진다. 아래 실험 또한 재사용이 거의 없는 셈플을 가지고 수행했더니, 오히려 살짝 느려 졌다. 

특이한 점은 아래처럼 inMemoryColumnarStorage.compressed 옵션을 켰더니 또 더 빨라 졌다는 점..... 
물론 compressing 은 case 별로 빨라질때도, 느려질때도 있음을 잘 알고 있다. 아마도 아래 Job 에서는 Columnar compressing 으로 인하여, shuffle 되는 양이 줄었기 때문인 듯...

아래 실험에서는 2번과 3번이 큰 효율을 보이고 있지는 않지만, 재사용이 많은, 그리고 재사용하는 테이블이 복잡한 헤비 쿼리(혹은 헤비 데이타)인 경우, 이론적으로는 훨씬 급격한 성능 향상을 꽤 할 수 있으리라 기대해본다.

관련 메뉴얼 : https://spark.apache.org/docs/1.1.0/sql-programming-guide.html#caching-data-in-memory


1. Default 수행
-> 647초 소요.


2. cacheTable 메소드 사용.
-> 679초 소요.


3. cacheTable 및 Colmanar Compress 옵션 사용
-> .set("spark.sql.inMemoryColumnarStorage.compressed", "true")
-> 557초 소요


2015년 4월 4일 토요일

Druid (Interactive Analytics at Scale) - 설치기

Druid 설치는.... 공식 Web Site 의 Getting Started 를 참조 했지만, 무지 skip이 많다.

http://druid.io/

홈페이지 대문에 링크되어 있는 Getting Started는 그대로 따라하면 대략 5~6개의 에러를 만난다. 대표적으로, wikipedia 셈플은 MySQL 디펜던시가 없다고 해놓구선, 실행해보면 mysql 관련 시도를 한다...

물론 config 쪽에서 MySQL 접근을 하지 않도록 하는 방법도 있겠지만, Sample  만 돌리고 말것도 아니므로...대략적인 Full Setting 을 해 보았다. 기타 기본적인 세팅과 데몬 구동이 필수 필요함에도, Getting Started  는 모든걸 skip 하고 있었다.

어찌되었든, Getting Started 가 좀 비약이 심하지만, 나머지 Document 정리는 잘 되어 있는 느낌이다. github 내 소스들도 최근에도 활발히 소스 갱신이 있었음을 확인 하였다.

[Druid Dowload & install & Setting]

  1. wget http://static.druid.io/artifacts/releases/druid-0.7.0-bin.tar.gz
  2. tar xvzf druid*.tar.gz
  3. Download Zookeeper & Setting
    1. wget http://mirror.apache-kr.org/zookeeper/zookeeper-3.3.6/zookeeper-3.3.6.tar.gz
    2. tar xvzf zookeeper-3.3.6.tar.gz
    3. cp conf/zoo_sample.cfg conf/zoo.cfg
    4. ./bin/zkServer.sh start
  4. Install MySQL & initial Setting
    1. sudo yum install -y mysql-server
    2. sudo service mysql start
    3. mysql -u root
    4. GRANT ALL ON druid.* TO 'druid'@'localhost' IDENTIFIED BY 'diurd'; 
      CREATE DATABASE druid DEFAULT CHARACTER SET utf8;
  5. Coordinator Node settings
    1. 주석제거
      1. druid.host=localhost
        druid.port=8081
    2. strart
      1. java -Xmx256m -Duser.timezone=UTC -Dfile.encoding=UTF-8 -classpath config/_common:config/coordinator:lib/* io.druid.cli.Main server coordinator
  6. Historical Node settings
    1. 주석제거
      1. druid.host=localhost druid.port=8083
    2. start
      1. java -Xmx256m -Duser.timezone=UTC -Dfile.encoding=UTF-8 -classpath config/_common:config/historical:lib/* io.druid.cli.Main server historical
  7. Broker Node Settings
    1. 주석제거
      1. druid.host=localhost druid.port=8082
    2. start
      1. java -Xmx256m -Duser.timezone=UTC -Dfile.encoding=UTF-8 -classpath config/_common:config/broker:lib/* io.druid.cli.Main server broker
  8. Realtime Node Settings
    1. 주석제거
      1. druid.host=localhost druid.port=8084
    2. start
      1. java -Xmx512m -Duser.timezone=UTC -Dfile.encoding=UTF-8 -Ddruid.realtime.specFile=examples/wikipedia/wikipedia_realtime.spec -classpath config/_common:config/realtime:lib/* io.druid.cli.Main server realtime
      2. realtime 으로 데이타를 가져오는 것까지 준비가 되어 있다. example 로 우선 구동 태스트를 해 보았으며, 결과를 빠르게 확인해보기 위해서는 위 .spec 파일을 열어 수집 갱신 주기를 바꾸어 주면 가능하다.
위 처럼 Coordinator ip:port 를 브라우저에서 치면, web ui 를 볼 수 있다.
아래처럼 저장해둔 example query 를 콘솔에서 restful url 로 수행해 보자 결과가 json 으로 떨어진다. 즉, WebService 를 위한 별도의 WAS 나 Gateway Ajax 용 호스팅 Web Page 를 만들지 않아도 된다.
일단, 오늘은 싱글노드 설치 & 쿼리 결과 보는 것 까지...!!!!




Druid (Interactive Analytics at Scale) - 시작기

Druid 를 시작했다.

그전에 여러가지 아키텍처에 대하여 고민 및 조사를 해보았고, 현재 우리 Production 에 존재하는 여러 NoSQL과 In-Memory 엔진의 조합도 고려해 보았었다.

* 요건
-> 테라 단위, 초 대용량 단일 테이블에 수많은 컬럼에 대한 Group By & Aggregation 요건
-> 일 수십 기가 insert (insert 는 현재는 준 실시간. 향후는 실시간 insert)
-> 리얼타임 Group By & Aggregation 분석용 쿼리가 수초 이내에 답이 나오는것이 목표.
-> 동시에 여러 사람이 쿼리를 날릴 수 있음.

이 문제를 풀기 위해, 고려해본 Legacy hadoop Eco 시스템 활용 시나리오 들은 아래와 같다.

  1. Hash 기반 NoSQL
    1. 우리가 가지고 있는 Hash 기반 NoSQL 은 이 시나리오 에서는 고려의 가치가 없다.
    2. Hash 기반 NoSQL 들은 요런 시나리오 에서는 MySQL보다도 못한 성능 벤치마크 blog들을 많이 본적 있어서, 실험도 하지 않기로 했다.
  2. Range Dictionary 기반 NoSQL
    1. 범위가 있는 경우 HBase 는 MongoDB나 Casandra 보다 월등한 성능을 보인다. Group By 시 Grouping Key 가 소수일때는 PK 설계를 잘 하면, 그런데로 좋은 성능을 보일 수 있다.
    2. 그러나, 우리의 시나리오 에서는 Grouping Key가 15개에 달한다. 해당 Key가 항상 등장하면 또 가능하다. 그러나, 그중 팩토리얼 개수의 조합으로 Dynamic 하게 key 가 선별적으로 조회 요청 될 때는 답이 안나올게 불보듯 뻔함. SKIP. 
  3. RDBMS
    1. 테이블 1개가 테라 단위 이상일 때는 MySQL 샤딩도 답이 안나온다.
    2. 사실 MySQL 은 컬럼이 많을때 300기가만 넘어도 100초가 훌쩍 넘어간다. (1대 기준이긴 하지만... RDBMS 는 scale out 을 할수도 없고, 하더라도 MPP 방식이 아닌지라... 2~3대가 한계... )
    3. Oracle  이나 Maria 디비가 후보군으로 더 고려 가능하지만.... 대동소이 할것으로 사료 되므로...SKIP.
    4. 우측 그림은 Machine 1대 기준 Aggregation 쿼리에 대한 MySQL vs Druid 의 수행시간 비교 자료.
  4. ElasticSearch RealTime Search Engine
    1. ElasticSearch가 훌륭한 Group By Aggregation Query String 을 지원하지만, 이 역시 Hash 기반이라 성능을 기대하지는 않는다.
    2. 단, ElasticSearch 에서는 셈플링하여 확률 기반으로 Aggregation 결과를 뿌려 주는 기능을 제공한다. 트랜드를 보는 BI 시나리오에서의 활용은, 정확도를 약간(threshold 값으로 정확도를 정교하게 trade off 가능) 포기 하고, 속도를 취할 수 있어 고려해볼 만 하다고 생각하여 후보군으로 올려 두었다.
    3. 하지만, 저정도의 크기를 테스트 하기에 우리 ElasticSearch 의 Node 대수가 현재는 너무 작다... 곧 늘릴 거긴 하지만... 
  5. Spark를 통한 선 집계 
    1. Spark 는 훌륭한 In-Memory 배치 시스템으로 완벽하게 현재 재 역할을 해주고 있지만, 이 시나리오 에서는 Spark 배치도 답이 안나온다.
    2. 그 조합이 1억 개에 가깝기 때문이다.
    3. 또한 그간의 Production 운영 경험 상. RDD가 전체 병렬 Node 메모리 합보다 훨씬 커지기 시작하면, 기하급수적으로 속도가 느려 짐을 경험한 바 있다.(Hive 나 M/R 보다는 훨씬 빠르지만..)
  6. Spark 를 데몬화 하여 on the fly 로 처리
    1. Spark 를 Spark Streaming + Mesos + Marathon 의 조합으로 데모나이즈 화 해놓고, On the Fly 로 반응하게 하는 시나리오는 추가로 실험해볼 예정이다. 
    2. Spark streaming 은 CEP 엔진이지, 이런 시나리오를 위한 엔진은 아니므로, 큰 기대를 하고 있지는 않다.
  7. 현재 Legacy 로는 존재하지 않지만, Aggregation 에 최적화된 별도 NoSQL고려.
    1. 가장 현실성 높은 시나리오 이다.
    2. 요 시나리오를 우선 최우선 고려.
    3. 여러가지 NoSQL 중 Druid 선정.
그래서 Group By Aggregation 에 최적화된 NoSQL 관련 여러 NoSQL 을 고려 하던 중, 우선 Druid 를 직접 설치, 우리의 Real 요건을 가지고 Real Data 로 가능성을 타진 해 보기 위한 설치 테스트를 진행해보기로 하였다.

Druid 또한 2010년도 Google 의 Dremel 논문의 영향을 받은 In-Memory 기반 SQL 을 지원하는 NoSQL이다. (공식 홈페이지 : http://druid.io/ )

아래는 Druid 를 선정하기까지 고려한 여러 아티클 들이다.


  1. http://druid.io/blog/2011/04/30/introducing-druid.html
    1. 성능 벤치마크 자료
    2. 좀 오래전 자료라, 요즘에는 이보다 훨씬 성능이 좋으리라 기대한다.
  2. http://druid.io/blog/2014/03/17/benchmarking-druid.html
    1. 역시 성능 벤치마크 자료
    2. 작년 자료라 첫번째 자료보다는 신빙성이 간다.
    3. MySQL 과는 천양지차의 압도적인 성능을 보여준다. 사실 MySQL은 테이블 한개가 천문학적인 크기로 커질 때는 샤딩으로도 답이 없다. 뭐 여타의 RDBMS 가 다 그러하지만...
  3. https://github.com/pulsarIO/realtime-analytics/wiki
    1. ebay 가 오픈소스로 오픈한 realtime-analytics 프레임워크
    2. 내부에 druid 와 casandra 등 nosql  과의 colaboration mesh up 이 되어 있다. 
  4. https://www.linkedin.com/pulse/20140909054748-5574162-true-performance-measure-of-realtime-big-data-analytics-platforms
    1. 빅데이타 에코시스템의 강자 Linked-in이 realtime analytics  로 내부 고려하며 남긴 아티클.
    2. 상용1개(parstream)와 druid 를 최종 후보로 선정. ( 함께 비교한 Riak 은 성능이 좋지 않음을 확인 한 문구가 보인다. MongoDB 와 Casandra 는 해볼필요도 없다는 투의 문구도 보인다. 사실 그런 류의 Key Value 스토어 에서의 Group By Aggregation 은 자료구조 상 빠를래야 빠를 수가 없다.)
  5. http://druid.io/
    1. druid 공식 홈페이지.
    2. 홈페이지는 나름 잘 정리되어 있다.
    3. getting started 는 지금 여러 방식으로 설치 중인데...최악이다.