네이티브 쿼리

네이티브 쿼리 (Native queries)

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

Druid의 네이티브 쿼리는 JSON 객체이며 보통 Broker나 Router 프로세스에 발행돼요. 쿼리는 이렇게 POST할 수 있어요.

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

본문

curl -X POST '<queryable_host>:<port>/druid/v2/?pretty' -H 'Content-Type:application/json' -H 'Accept:application/json' -d @<query_json_file>

<queryable_host>:<port>는 시스템에 맞는 주소와 포트로 바꾸세요. 예를 들어 quickstart 설정을 실행 중이라면 <queryable_host>:<port>localhost:8888로 바꾸면 됩니다.

네이티브 쿼리를 웹 콘솔의 Query 뷰에 직접 입력할 수도 있어요. 콘솔에 네이티브 쿼리를 붙여넣기만 하면 에디터가 자동으로 JSON 모드로 바뀌지요.

Druid의 네이티브 쿼리 언어는 HTTP 위의 JSON이에요. 다만 커뮤니티의 많은 분들이 Druid를 쿼리하는 다른 언어의 클라이언트 라이브러리를 기여해 주기도 했습니다.

Content-Type/Accept 헤더는 'application/x-jackson-smile'도 받을 수 있어요.

curl -X POST '<queryable_host>:<port>/druid/v2/?pretty' -H 'Content-Type:application/json' -H 'Accept:application/x-jackson-smile' -d @<query_json_file>

Accept 헤더를 제공하지 않으면 Content-Type 헤더의 값으로 기본 설정돼요.

Druid의 네이티브 쿼리는 비교적 저수준이라, 내부에서 계산이 수행되는 방식과 밀접하게 대응돼요. Druid 쿼리는 가볍고 매우 빨리 끝나도록 설계됐어요. 따라서 더 복잡한 분석이나 더 복잡한 시각화를 만들려면 Druid 쿼리 여러 개가 필요할 수 있어요.

쿼리는 보통 Broker나 Router로 보내지만, Historical 프로세스와 스트리밍 수집 태스크를 실행 중인 Peon(태스크 JVM)도 쿼리를 받을 수 있어요. 특정 프로세스가 서비스하는 특정 세그먼트의 결과를 조회하고 싶다면 유용해요.

사용 가능한 쿼리

Druid는 다양한 유스케이스를 위한 수많은 쿼리 타입을 가져요. 쿼리는 여러 JSON 프로퍼티로 구성되며 Druid는 유스케이스마다 다른 쿼리 타입을 제공해요. 각 쿼리 타입 문서는 설정 가능한 모든 JSON 프로퍼티를 설명합니다.

집계 쿼리 (Aggregation queries)

메타데이터 쿼리 (Metadata queries)

기타 쿼리

어떤 쿼리 타입을 써야 할까

집계 쿼리에서 둘 이상이 요구를 충족한다면, 가능하면 Timeseries나 TopN을 쓰는 걸 일반적으로 권장해요. 자기 유스케이스에 특화 최적화돼 있기 때문이에요. 그 둘 다 안 맞는다면 가장 유연한 GroupBy 쿼리를 쓰면 됩니다.

쿼리 취소 (Query cancellation)

쿼리는 고유 식별자를 사용해 명시적으로 취소할 수 있어요. 쿼리 식별자가 쿼리 시점에 설정됐거나 별도로 알려져 있다면, Broker나 Router에서 다음 엔드포인트로 쿼리를 취소할 수 있어요.

DELETE /druid/v2/{queryId}

예를 들어 쿼리 ID가 abc123이면 쿼리를 이렇게 취소할 수 있어요.

curl -X DELETE "http://host:port/druid/v2/abc123"

쿼리 오류 (Query errors)

인증·권한 실패

보안 설정된 Druid 클러스터에서 인증 실패 시 쿼리 요청은 HTTP 401 응답 코드로 응답해요. 권한 실패 시에는 HTTP 403 응답 코드가 반환됩니다.

쿼리 실행 실패

쿼리가 실패하면 Druid는 HTTP 응답 코드와 함께 다음 구조의 JSON 객체를 반환해요.

{
  "error" : "Query timeout",
  "errorMessage" : "Timeout waiting for task.",
  "errorClass" : "java.util.concurrent.TimeoutException",
  "host" : "druid1.example.com:8083"
}

응답의 필드는 다음과 같아요.

field description
error 잘 정의된 오류 코드(아래 참고).
errorMessage 오류에 대한 추가 정보를 담은 자유 형식 메시지. null일 수 있어요.
errorClass 이 오류를 일으킨 예외의 클래스. null일 수 있어요.
host 이 오류가 발생한 호스트. null일 수 있어요.

error 필드에 올 수 있는 Druid 오류 코드는 다음과 같아요.

오류 코드 HTTP 응답 코드 설명
SQL parse failed 400 SQL 쿼리에서만 발생. SQL 쿼리 파싱에 실패했어요.
Plan validation failed 400 SQL 쿼리에서만 발생. SQL 쿼리 검증에 실패했어요.
Resource limit exceeded 400 쿼리가 설정된 리소스 한도(예: groupBy maxResults)를 초과했어요.
Query capacity exceeded 429 쿼리 제출 시점에 가용 리소스가 부족해 실행에 실패했어요. 리소스는 쿼리 스케줄러 lane 용량, merge buffer 같은 런타임 리소스일 수 있어요. 오류 메시지에 실패에 대한 자세한 내용이 담겨 있어요.
Unsupported operation 501 쿼리가 지원되지 않는 연산을 시도했어요. 문서화되지 않은 기능이나 불완전하게 구현된 익스텐션을 쓸 때 발생할 수 있어요.
Query timeout 504 쿼리가 타임아웃됐어요.
Query interrupted 500 쿼리가 중단됐어요. JVM 종료 때문일 수 있어요.
Query cancelled 500 쿼리 취소 API로 쿼리가 취소됐어요.
Truncated response context 500 쿼리의 중간 응답 컨텍스트가 내장 한도인 7KiB를 초과했어요.

응답 컨텍스트는 Druid 서버가 서로에게 쿼리 결과를 보낼 때 대역외(out-of-band) 정보를 공유하는 내부 데이터 구조예요. HTTP 헤더에 직렬화되며 최대 길이는 7KiB예요. 이 오류는 Historical 같은 데이터 서버가 Broker로 보낸 중간 응답 컨텍스트가 이 한도를 초과할 때 발생해요.

응답 컨텍스트는 여러 용도로 쓰이지만 큰 컨텍스트를 만들기 가장 쉬운 건 쿼리 중 움직이는 세그먼트에 대한 정보를 공유하는 경우예요. 즉 Broker가 쿼리를 발행한 시점과 Historical에서 처리된 시점 사이에 매우 많은 세그먼트가 움직였음을 나타낼 수 있어요. 정상 운영 중엔 거의, 어쩌면 아예 발생하지 않아야 해요.
Unknown exception 500 그 밖의 다른 예외가 발생했어요. errorMessage와 errorClass에서 세부 내용을 확인하되, 이 필드들은 자유 형식이라 릴리스마다 바뀔 수 있다는 점을 유의하세요.

더 알아보기