[ Druid Data set ]
Druid의 모든 데이터는 Time 기준의 Segment라는 단위로 저장하고, 이 segment는 Timestamp, Dimension, Measure 이 세가지 필수 요소로 구성되어 있다.
- Timestamp : 모든 query는 time을 기반으로 실행
- Dimension : event의 string 속성들
- Measure : 실제 집계할 컬럼.
[ Data Ingestion ]
1. hadoop dir(http://bisnapshotm01.ssgbi.com:50070/explorer.html#/)에 create external로 데이터를 떨군다.
2. JSON 형식의 데이터 로드 쿼리를 overlord node(8090)로 submit 한다.
> disp_ctg_load.json
{
"type": "index_hadoop",
"spec": {
"ioConfig": {
"type": "hadoop",
"inputSpec": {
"type": "static",
"paths": "/apps/hive/warehouse/snapshot.db/disp_ctg_item_all_column/"
}
},
"dataSchema": {
"dataSource": "DISP_CTG_ITEM__ORG_ITEM",
"granularitySpec": {
"type": "uniform",
"segmentGranularity": "day",
"queryGranularity": "day",
"intervals": [ "2017-01-01/2018-01-01" ]
},
"parser": {
"type": "hadoopyString",
"parseSpec": {
"format": "tsv",
"columns": [
"기준일자",
"전시카테고리ID",
"표준카테고리ID",
"상품ID",
.........
],
"delimiter": "\t",
"dimensionsSpec": {
"dimensions": [
"기준일자",
"전시카테고리ID",
"표준카테고리ID",
....
]
},
"timestampSpec": {
"format": "auto",
"column": "기준일자"
}
}
},
"metricsSpec": [
{
"name": "상품ID",
"type": "hyperUnique",
"fieldName": "상품ID"
}
]
},
"tuningConfig": {
"type": "hadoop",
"partitionsSpec": {
"type": "hashed",
"targetPartitionSize": 5000000
},
"jobProperties": { }
}
}
}
> http curl command
curl -X 'POST' -H 'Content-Type:application/json' -d @disp_ctg_load.json bisnapshotd01.ssgbi.com:8090/druid/indexer/v1/task
이 때, segmentGranularity <= queryGranularity 이 성립.
(granularity : all, none, second, minute, fifteen_minute, thirty_minute, hour, day, week, month, quarter and year.)
overlord submit 후에, MR JOB이 2번 실행된다.
1) Determine partitions
: 설정 정보(Granularity, tuningConfig 등)에 따라 segment의 shard 개수를 결정하는 작업이다.
2) Index Generation
: index segment를 수행하는 작업이다. (segment 생성)
time 단위로 데이터를 sharding 하며, sharding 된 데이터를 segment라고 한다.
이 과정이 끝나면 broker node로 해당 데이터 소스에 대한 query가 가능하다.
* ingestion 과정에서 map, reduce 메모리 오류가 나서, 각각 16GB로 늘려주었다.
3. Delete data
: 3단계가 필요하다.
1) disable datasource
curl -X 'DELETE' "bisnapshotd01.ssgbi.com:8081/druid/coordinator/v1/datasources/DISP_CTG_ITEM__ORG_ITEM"
2) delete data - 삭제할 interval을 설정해주어야 한다. (coordinator에 kill task 올라옴)
curl -X 'DELETE' bisnapshotd01.ssgbi.com:8081/druid/coordinator/v1/datasources/DISP_CTG_ITEM__ORG_ITEM/intervals/2017-01-01T00:00:00Z_2018-01-01T00:00:00Z
3) enable datasource
curl -X 'POST' "bisnapshotd01.ssgbi.com:8081/druid/coordinator/v1/datasources/DISP_CTG_ITEM__ORG_ITEM"
* Granularity
> 아래 세가지는 query 시, granularity
1) simple granularity
: all, none, second, minute, fifteen_minute, thirty_minute, hour, day, week, month, quarter and year
2) duration granularity
"granularity" : {"type" : "duration", "duration": 3600000, "origin": "2012-01-01T00:30:00Z"}
-> "2012-01-01T00:30:00Z" 이 시각을 기준으로, 1시간 단위 집계
3) period granularity
"granularity" : {"type" : "period ", "period ": P3M, "origin": "2012-01-01T00:00:00Z"}
-> "2012-01-01T00:00:00Z" 이 시각을 기준으로, 3개월 단위 집계
> 아래는 data ingestion 시, segmentGranularity
Enum Constant and Description |
---|
ALL |
DAY |
FIFTEEN_MINUTE |
FIVE_MINUTE |
HOUR |
MINUTE |
MONTH |
NONE |
QUARTER |
SECOND |
SIX_HOUR |
TEN_MINUTE |
THIRTY_MINUTE |
WEEK |
YEAR |
=> "granularitySpec": {
"type": "period",
"segmentGranularity": {"type":"period", "period":"P3D"}, -- ISO 8601 방식
"queryGranularity": "day",
"intervals": [ "2017-01-01/2017-01-08" ]
},
> 2017-01-01/2017-01-08, P3D로 올렸는데, 실제로는 2016-12-31/2017-01-03/2017-01-06으로 나누어져 올라감
> 2017-01-01부터 3DAYS로 나누려면, segmentGranularity에 "origin": "2017-01-01"를 설정해주면 된다.
groupby query 결과,
/*
3day segment로 올렸을때,
*/
1)
SELECT 기준일자, COUNT(DISTINCT 상품ID) FROM HDFS_DISP_CTG_ITEM_ALL_COLUMN_20180403 WHERE 기준일자 BETWEEN '20170101' AND '20170107' GROUP BY 기준일자 ORDER BY 기준일자
{
"queryType": "groupBy",
"dataSource": "DISP_CTG_ITEM__ORG_ITEM_0403",
"dimensions": [
],
"granularity": "day",
"aggregations": [
{
"type": "distinctCount",
"name": "상품수",
"fieldName": "상품ID"
}
],
"intervals": [
"2017-01-01T00:00:00/2017-01-08T00:00:00"
]
}
-- 오차율 0%
2)
SELECT COUNT(DISTINCT 상품ID) FROM HDFS_DISP_CTG_ITEM_ALL_COLUMN_20180403 WHERE 기준일자 BETWEEN '20161231' AND '20170102'
{
"queryType": "groupBy",
"dataSource": "DISP_CTG_ITEM__ORG_ITEM_0403",
"dimensions": [
],
"granularity": {"type":"period", "period":"P3D"},
"aggregations": [
{
"type": "distinctCount",
"name": "상품수",
"fieldName": "상품ID"
}
],
"intervals": [
"2017-01-01T00:00:00/2017-01-08T00:00:00"
]
}
3) segmentGranularity (P3D) 보다 작은 단위 (약수단위)로 GROUPBY SELECT 했을 때
오차율 0% -> 예를 들면, segmentGranularity=P6D면, 1,2,3,6일 단위로 GROUPBY 하면 정합성 100%
"granularity": {"type":"period", "period":"P1D"},
SELECT COUNT(DISTINCT 상품ID) FROM HDFS_DISP_CTG_ITEM_ALL_COLUMN_20180403 WHERE 기준일자 ='20170101'
-- 오차율 0%
* ISO 8601 형식
기간 : 기간 표현의 시작을 알리는 기간지정자 P(period)로 시작. T는 시간표현 앞에 오는 시간 지정자.
= P<date>T<time>
-> P[n]Y[n]M[n]DT[n]H[n]M[n]S / P[n]W 형식으로 표현된다.
[ Querying ]
: HTTP REST 방식으로 Broker node(8082)에 쿼리한다. (query : json format)
curl -X POST 'bisnapshotm01.ssgbi.com:8082/druid/v2/?pretty' -H 'Content-Type:application/json' -d @query.json -w %{time_total} > out.json
json 형식의 쿼리는 'Druid Distinct count 성능테스트'에서 함께 설명.
* 참고
http://druid.io/docs/0.12.0/design/index.html
https://www.slideshare.net/freepsw/olap-for-big-data-druid-vs-apache-kylin-vs-apache-lens
http://www.popit.kr/time-series-olap-druid-%EC%9E%85%EB%AC%B8/