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초 소요.
-> 647초 소요.
2. cacheTable 메소드 사용.
-> 679초 소요.
3. cacheTable 및 Colmanar Compress 옵션 사용
-> .set("spark.sql.inMemoryColumnarStorage.compressed", "true")
-> 557초 소요