DataSketches 통합

DataSketches 통합 (Datasketches Integration)

Apache DataSketches(https://datasketches.apache.org/)는 HIVE-22939를 통해 Hive에 통합되었어요. 이를 통해 일반 SQL 문으로 다양한 스케치(sketch) 연산을 수행할 수 있게 됩니다. 스케치는 분산 데이터의 대략적인 집계(예: 고유값 추정, 분위수)를 메모리 효율적으로 계산하는 기법이에요.

출처: 문서

본문

스케치 함수 (Sketch functions)

명명 규칙 (Naming convention)

모든 스케치 함수는 다음 명명 규칙으로 등록되어요.

ds_{sketchType}_{functionName}

예를 들어 ds_hll_estimate라는 함수는 hll 스케치로부터 고유값(distinct values)을 추정하는 데 사용할 수 있어요.

sketchType

스케치 자체에 대한 자세한 정보는 datasketches 사이트를 참고하세요.

  • frequency
  • hll
  • cpc
  • theta
  • frequent items
  • freq
  • histogram
  • skll

functionName

name description
sketch generates sketch data from input
estimate computes the estimate for frequency related sketches
union aggregate function to merge multiple sketches
union_f unions 2 sketches given in the arguments
n number of elements
cdf cumulative distribution
rank estimates the rank of the given element; returns a value in the range of 0~1
intersect aggregate to intersect multiple sketches
intersect_f intersect 2 sketches given in the arguments
stringify returns the the sketch in a more readable form

선언된 스케치 함수 목록 (List declared sketch functions)

약 60개의 함수가 등록되어 있으므로, 개별 UDF를 나열하거나 정보를 얻는 것도 고려해 보는 걸 권장해요.

ds_ 접두어가 붙은 모든 함수를 나열하려면 다음을 사용하세요.

show functions like 'ds_%';

함수의 설명에 접근하려면 다음처럼 합니다.

desc function ds_freq_sketch;

구체화 뷰(Materialized Views)와의 통합

스케치 집계는 일부 확장을 통해 Calcite에 노출되어, 더 작은 차원의 쿼리에서 MV를 사용하거나 증분 업데이트를 가능하게 해 줘요.

BI 모드 (BI mode)

일부 정확도를 희생할 수 있다면 스케치 사용은 성능 향상을 가져올 수 있어요. 차트나 라이브 대시보드에서 특히 유용합니다. BI 모드는 가능하면 자동으로 스케치 함수로 재작성(rewrite)하는 기능이에요.

BI 모드는 다음으로 활성화할 수 있어요.

set hive.optimize.bi.enabled=true;

COUNT(DISTINCT(X)) 재작성

이 기능은 hive.optimize.bi.rewrite.countdistinct.enabled conf 키로 켜고 끌 수 있어요.

사용되는 고유값 스케치 계열은 hive.optimize.bi.rewrite.countdistinct.sketch 로 설정할 수 있어요 (현재는 hll만 사용 가능).

이 기능은 다음 쿼리를

select category, count(distinct id) from sketch_input group by category

고유값 카운트 스케치를 사용해 답하는 쿼리로 재작성할 수 있어요.

select category, round(ds_hll_estimate(ds_hll_sketch(id))) from sketch_input

percentile_disc(p) within group(order by x) 재작성

이 기능은 hive.optimize.bi.rewrite.percentile_disc.enabled conf 키로 켜고 끌 수 있어요.

사용되는 히스토그램 스케치 계열은 hive.optimize.bi.rewrite.percentile_disc.sketch 로 설정할 수 있어요 (현재는 kll만 사용 가능).

이 기능은 다음 쿼리를

select percentile_disc(0.3) within group(order by id) from sketch_input

히스토그램 스케치를 사용해 답하는 쿼리로 재작성할 수 있어요.

select ds_kll_quantile(ds_kll_sketch(id), 0.3) from sketch_input

cume_dist() over (order by id) 재작성

이 기능은 hive.optimize.bi.rewrite.cume_dist.enabled conf 키로 켜고 끌 수 있어요.

사용되는 히스토그램 스케치 계열은 hive.optimize.bi.rewrite.cume_dist.sketch 로 설정할 수 있어요 (현재는 kll만 사용 가능).

select id,cume_dist() over (order by id) from sketch_input

히스토그램 스케치를 사용해 답하는 쿼리로 재작성:

SELECT id, CAST(DS_KLL_RANK(t2.sketch, idVal) AS DOUBLE) 
FROM (SELECT id, CAST(COALESCE(CAST(id AS FLOAT), 340282346638528860000000000000000000000) AS FLOAT) AS idVal FROM sketch_input) AS t,
(SELECT DS_KLL_SKETCH(CAST(id AS FLOAT)) AS sketch FROM sketch_input) AS t2

NTILE 재작성

이 기능은 hive.optimize.bi.rewrite.ntile.enabled conf 키로 켜고 끌 수 있어요.

사용되는 히스토그램 스케치 계열은 hive.optimize.bi.rewrite.ntile.sketch 로 설정할 수 있어요 (현재는 kll만 사용 가능).

이 기능은 다음 쿼리를

select id,
       ntile(4) over (order by id
from sketch_input
order by id

NTILE 값을 계산하기 위해 히스토그램 스케치를 사용하도록 재작성할 수 있어요.

select id,
        case when ceil(ds_kll_cdf(ds, CAST(id AS FLOAT) )[0]*4) < 1 then 1 else ceil(ds_kll_cdf(ds, CAST(id AS FLOAT) )[0]*4) end
from sketch_input
join ( select ds_kll_sketch(cast(id as float)) as ds from sketch_input ) q
order by id
select id,
                rank() over (order by id),
                case when ds_kll_n(ds) < (ceil(ds_kll_rank(ds, CAST(id AS FLOAT) )*ds_kll_n(ds))+1) then ds_kll_n(ds) else (ceil(ds_kll_rank(ds, CAST(id AS FLOAT) )*ds_kll_n(ds))+1) end

RANK 재작성

이 기능은 hive.optimize.bi.rewrite.rank.enabled conf 키로 켜고 끌 수 있어요.

사용되는 히스토그램 스케치 계열은 hive.optimize.bi.rewrite.rank.sketch 로 설정할 수 있어요 (현재는 kll만 사용 가능).

select id,
       rank() over (order by id)
from sketch_input
order by id

이 쿼리는 다음과 같이 재작성돼요.

select id,
       case when ds_kll_n(ds) < (ceil(ds_kll_rank(ds, CAST(id AS FLOAT) )*ds_kll_n(ds))+1) then ds_kll_n(ds) else (ceil(ds_kll_rank(ds, CAST(id AS FLOAT) )*ds_kll_n(ds))+1) end
from sketch_input
join ( select ds_kll_sketch(cast(id as float)) as ds from sketch_input ) q
order by id

예제 (Examples)

HLL을 사용한 간단한 고유값 카운팅

  • 샘플 테이블 준비
create table sketch_input (id int, category char(1))
STORED AS ORC
TBLPROPERTIES ('transactional'='true');

insert into table sketch_input values
  (1,'a'),(1, 'a'), (2, 'a'), (3, 'a'), (4, 'a'), (5, 'a'), (6, 'a'), (7, 'a'), (8, 'a'), (9, 'a'), (10, 'a'),
  (6,'b'),(6, 'b'), (7, 'b'), (8, 'b'), (9, 'b'), (10, 'b'), (11, 'b'), (12, 'b'), (13, 'b'), (14, 'b'), (15, 'b')
; 
  • 중간 테이블을 사용해 고유값을 계산하는데 HLL을 사용
-- build sketches per category
create temporary table sketch_intermediate (category char(1), sketch binary);
insert into sketch_intermediate select category, ds_hll_sketch(id) from sketch_input group by category;

-- get unique count estimates per category
select category, ds_hll_estimate(sketch) from sketch_intermediate;

-- union sketches across categories and get overall unique count estimate
select ds_hll_estimate(ds_hll_union(sketch)) from sketch_intermediate;
  • 중간 테이블 없이 HLL로 고유값 계산
select category, ds_hll_estimate(ds_hll_sketch(id)) from sketch_input group by category;
select ds_hll_estimate(ds_hll_sketch(id)) from sketch_input;
  • BI 모드를 통해 투명하게 HLL로 고유값 계산
set hive.optimize.bi.enabled=true;
select category,count(distinct id) from sketch_input group by category;
select count(distinct id) from sketch_input;
  • BI 모드를 통해 투명하게 HLL로 고유값 계산 - 중간 스케치를 저장하기 위해 Materialized View 활용
-- create an MV to store precomputed HLL values
create  materialized view mv_1 as
  select category, ds_hll_sketch(id) from sketch_input group by category;

set hive.optimize.bi.enabled=true;
select category,count(distinct id) from sketch_input group by category;
select count(distinct id) from sketch_input;

더 알아보기 (Learn more)

DataSketches 통합은 근사 집계(특히 고유값 추정)를 SQL에서 손쉽게 수행하게 해 줘요. set hive.optimize.bi.enabled=true;로 BI 모드를 켜면 count(distinct ...) 같은 일반 쿼리를 자동으로 스케치 함수로 재작성해 성능을 높일 수 있습니다.