타임시리즈 쿼리

타임시리즈 쿼리 (Timeseries queries)

Apache® Druid는 Druid SQL과 네이티브 쿼리(native queries) 두 가지 쿼리 언어를 지원해요. 이 문서는 네이티브 언어의 쿼리 타입 하나를 다룹니다. Druid SQL이 언제 이 쿼리 타입을 쓰는지는 SQL 문서를 참고하세요.

이 타입의 쿼리는 타임시리즈 쿼리 객체를 받아 JSON 객체 배열을 반환하는데, 각 객체는 타임시리즈 쿼리가 요청한 값을 하나씩 나타내요. 시간 버킷(granularity) 단위로 집계한 값을 시간순으로 돌려받고 싶을 때 쓰는 대표적인 쿼리예요.

출처: Apache Druid 공식 문서 — Timeseries queries

본문

타임시리즈 쿼리 객체 예시는 아래와 같아요.

{
  "queryType": "timeseries",
  "dataSource": "sample_datasource",
  "granularity": "day",
  "descending": "true",
  "filter": {
    "type": "and",
    "fields": [
      { "type": "selector", "dimension": "sample_dimension1", "value": "sample_value1" },
      { "type": "or",
        "fields": [
          { "type": "selector", "dimension": "sample_dimension2", "value": "sample_value2" },
          { "type": "selector", "dimension": "sample_dimension3", "value": "sample_value3" }
        ]
      }
    ]
  },
  "aggregations": [
    { "type": "longSum", "name": "sample_name1", "fieldName": "sample_fieldName1" },
    { "type": "doubleSum", "name": "sample_name2", "fieldName": "sample_fieldName2" }
  ],
  "postAggregations": [
    { "type": "arithmetic",
      "name": "sample_divide",
      "fn": "/",
      "fields": [
        { "type": "fieldAccess", "name": "postAgg__sample_name1", "fieldName": "sample_name1" },
        { "type": "fieldAccess", "name": "postAgg__sample_name2", "fieldName": "sample_name2" }
      ]
    }
  ],
  "intervals": [ "2012-01-01T00:00:00.000/2012-01-03T00:00:00.000" ]
}

타임시리즈 쿼리는 크게 7가지 부분으로 구성돼요.

property description required?
queryType 이 String은 항상 "timeseries"여야 해요. Druid가 쿼리를 어떻게 해석할지 가장 먼저 보는 값이에요. yes
dataSource 쿼리할 데이터 소스를 정의하는 String 또는 Object. 관계형 데이터베이스의 테이블과 아주 비슷해요. 자세한 건 DataSource 참고. yes
descending 결과를 내림차순 정렬할지 여부. 기본값은 false(오름차순)예요. no
intervals ISO-8601 인터벌을 나타내는 JSON Object. 쿼리를 실행할 시간 범위를 정의해요. yes
granularity 쿼리 결과를 버킷으로 나눌 granularity를 정의해요. Granularities 참고 yes
filter Filters 참고 no
virtualColumns 가상 컬럼의 JSON 목록. aggregationspostAggregations에서 가상 컬럼을 참조할 수 있어요. no (기본 none)
aggregations Aggregations 참고 no
postAggregations Post Aggregations 참고 no
limit 결과 수를 제한하는 정수. 기본은 무제한이에요. no
context grand totals빈 버킷 값을 포함해 쿼리 동작을 바꾸는 데 쓸 수 있어요. 모든 쿼리 타입에 적용되는 파라미터는 Query context reference도 참고. no

전부 종합하면, 위 쿼리는 "sample_datasource" 테이블에서 2012-01-01과 2012-01-03 사이의 각 날짜에 대해 데이터 포인트 2개를 반환해요. 각 데이터 포인트는 필터 집합에 대해 sample_fieldName1의 long 합, sample_fieldName2의 double 합, 그리고 sample_fieldName1을 sample_fieldName2로 나눈 double 결과가 돼요. 출력은 다음과 같아요.

[
  {
    "timestamp": "2012-01-01T00:00:00.000Z",
    "result": { "sample_name1": <some_value>, "sample_name2": <some_value>, "sample_divide": <some_value> }
  },
  {
    "timestamp": "2012-01-02T00:00:00.000Z",
    "result": { "sample_name1": <some_value>, "sample_name2": <some_value>, "sample_divide": <some_value> }
  }
]

Grand totals

Druid는 타임시리즈 결과셋의 마지막 행으로 "grand totals" 행을 하나 더 포함할 수 있어요. 이 기능을 켜려면 쿼리 컨텍스트에 "grandTotal" : true를 추가하세요. 예:

{
  "queryType": "timeseries",
  "dataSource": "sample_datasource",
  "intervals": [ "2012-01-01T00:00:00.000/2012-01-03T00:00:00.000" ],
  "granularity": "day",
  "aggregations": [
    { "type": "longSum", "name": "sample_name1", "fieldName": "sample_fieldName1" },
    { "type": "doubleSum", "name": "sample_name2", "fieldName": "sample_fieldName2" }
  ],
  "context": {
    "grandTotal": true
  }
}

grand totals 행은 결과 배열의 마지막 행으로 나타나고 timestamp가 없어요. 쿼리가 "descending" 모드로 실행돼도 마지막 행이에요. grand totals 행의 post-aggregation은 grand total 집계를 바탕으로 계산됩니다.

빈 버킷 값 (Empty bucket values)

기본적으로 Druid는 타임시리즈 쿼리 결과의 안쪽 빈 시간 버킷을 집계 함수의 기본값으로 채워요. 예를 들어 SUM 집계로 2012-01-01/2012-01-04 인터벌의 "day" granularity 타임시리즈 쿼리를 발행했는데 2012-01-02에 데이터가 없다면, Druid는 다음을 반환해요.

[
  {
    "timestamp": "2012-01-01T00:00:00.000Z",
    "result": { "sample_name1": <some_value> }
  },
  {
   "timestamp": "2012-01-02T00:00:00.000Z",
   "result": { "sample_name1": NULL }
  },
  {
    "timestamp": "2012-01-03T00:00:00.000Z",
    "result": { "sample_name1": <some_value> }
  }
]

데이터 인터벌을 완전히 벗어난 시간 버킷은 기본값으로 채워지지 않아요.

skipEmptyBuckets 컨텍스트 플래그로 모든 빈 버킷 채움을 끌 수 있어요. 이 모드에서 Druid는 결과에서 2012-01-02 데이터 포인트를 생략해요. 예:

{
  "queryType": "timeseries",
  "dataSource": "sample_datasource",
  "granularity": "day",
  "aggregations": [
    { "type": "longSum", "name": "sample_name1", "fieldName": "sample_fieldName1" }
  ],
  "intervals": [ "2012-01-01T00:00:00.000/2012-01-04T00:00:00.000" ],
  "context" : {
    "skipEmptyBuckets": "true"
  }
}

더 알아보기