SQL 기반 수집
SQL 기반 수집 (SQL-based ingestion) API
druid-multi-stage-query 확장을 사용한 SQL 기반 배치 수집 API를 다룹니다. MSQ 태스크 엔진에 쿼리를 제출하고 상태·리포트를 확인하며 취소하는 방법을 설명해요.
출처: 문서
본문
이 페이지는 Druid 24.0에서 새로 추가된
druid-multi-stage-query확장을 사용한 SQL 기반 배치 수집을 설명합니다. 어떤 수집 방법이 적합한지 결정하려면 ingestion methods 표를 참고하세요.
웹 콘솔의 Query 뷰는 multi-stage query 태스크 엔진(MSQ 태스크 엔진)과 multi-stage query 아키텍처에 친숙한 경험을 제공합니다. 프로그래밍 인터페이스가 필요 없으면 웹 콘솔 사용을 권장합니다.
MSQ 태스크 엔진에 API를 사용할 때, 취하려는 동작에 따라 사용하는 엔드포인트가 달라집니다.
/druid/v2/sql/task: 수집을 위한 쿼리를 제출합니다./druid/indexer/v1/task: 쿼리와 상호작용합니다. 여기에는 상태나 세부 정보를 가져오거나 쿼리를 취소하는 것이 포함됩니다. 이 페이지는 MSQ 태스크 엔진과 함께 사용할 수 있는 Overlord Task API 몇 가지를 설명합니다. Druid API에 대한 자세한 내용은 Druid의 API reference를 참고하세요.
이 문서에서 http://ROUTER_IP:ROUTER_PORT는 여러분의 Router 서비스 주소와 포트를 위한 자리표시자입니다. 이를 배포 정보로 교체하세요. 예를 들어 quickstart 배포라면 http://localhost:8888을 사용합니다.
쿼리 제출
MSQ 태스크 엔진에 쿼리를 제출합니다.
/druid/v2/sql/task 엔드포인트는 다음을 받습니다.
query,context,parameters필드를 사용하는 JSON-over-HTTP 형식의 SQL 요청. 이 엔드포인트는resultFormat,header,typesHeader,sqlTypesHeader필드는 무시합니다.INSERT및REPLACE문.SELECT쿼리 (실험적 기능). SELECT 쿼리 결과는 controller가 워커에서 수집해 배열의 배열 형태로 태스크 리포트에 기록합니다.INSERT나REPLACE없는 일반SELECT쿼리의 동작과 결과 형식은 변경될 수 있어요.
URL
POST /druid/v2/sql/task
응답
- 200 SUCCESS — 쿼리를 성공적으로 제출함
- 400 BAD REQUEST — 잘못된 쿼리로 인한 오류. 다음 형식의 오류를 자세히 설명하는 JSON 객체를 반환합니다.
{
"error": "A well-defined error code.",
"errorMessage": "A message with additional details about the error.",
"errorClass": "Class of exception that caused this error.",
"host": "The host on which the error occurred."
}
- 500 INTERNAL SERVER ERROR — 예상치 못한 조건으로 요청이 전송되지 않음. 다음 형식의 오류를 자세히 설명하는 JSON 객체를 반환합니다.
{
"error": "A well-defined error code.",
"errorMessage": "A message with additional details about the error.",
"errorClass": "Class of exception that caused this error.",
"host": "The host on which the error occurred."
}
샘플 요청
다음 예시는 외부 JSON 소스에서 데이터를 가져와 wikipedia라는 테이블에 삽입하는 쿼리를 보여줍니다. 예시는 두 개의 쿼리 컨텍스트 파라미터를 지정합니다.
maxNumTasks=3: 최대 병렬 태스크 수를 3으로 제한합니다.finalizeAggregations=false: Druid가 수집 중에 집계의 중간 타입을 저장하도록 보장합니다. 자세한 내용은 Rollup을 참고하세요.
HTTP
POST /druid/v2/sql/task HTTP/1.1
Host: http://ROUTER_IP:ROUTER_PORT
Content-Type: application/json
{
"query": "SET maxNumTasks=3;\nSET finalizeAggregations=false;\nINSERT INTO wikipedia\nSELECT\n TIME_PARSE(\"timestamp\") AS __time,\n *\nFROM TABLE(\n EXTERN(\n '{\"type\": \"http\", \"uris\": [\"https://druid.apache.org/data/wikipedia.json.gz\"]}',\n '{\"type\": \"json\"}',\n '[{\"name\": \"added\", \"type\": \"long\"}, {\"name\": \"channel\", \"type\": \"string\"}, {\"name\": \"cityName\", \"type\": \"string\"}, {\"name\": \"comment\", \"type\": \"string\"}, {\"name\": \"commentLength\", \"type\": \"long\"}, {\"name\": \"countryIsoCode\", \"type\": \"string\"}, {\"name\": \"countryName\", \"type\": \"string\"}, {\"name\": \"deleted\", \"type\": \"long\"}, {\"name\": \"delta\", \"type\": \"long\"}, {\"name\": \"deltaBucket\", \"type\": \"string\"}, {\"name\": \"diffUrl\", \"type\": \"string\"}, {\"name\": \"flags\", \"type\": \"string\"}, {\"name\": \"isAnonymous\", \"type\": \"string\"}, {\"name\": \"isMinor\", \"type\": \"string\"}, {\"name\": \"isNew\", \"type\": \"string\"}, {\"name\": \"isRobot\", \"type\": \"string\"}, {\"name\": \"isUnpatrolled\", \"type\": \"string\"}, {\"name\": \"metroCode\", \"type\": \"string\"}, {\"name\": \"namespace\", \"type\": \"string\"}, {\"name\": \"page\", \"type\": \"string\"}, {\"name\": \"regionIsoCode\", \"type\": \"string\"}, {\"name\": \"regionName\", \"type\": \"string\"}, {\"name\": \"timestamp\", \"type\": \"string\"}, {\"name\": \"user\", \"type\": \"string\"}]'\n )\n)\nPARTITIONED BY DAY"
}
cURL
curl --location --request POST 'http://ROUTER_IP:ROUTER_PORT/druid/v2/sql/task' \
--header 'Content-Type: application/json' \
--data '{
"query": "SET maxNumTasks=3;\nSET finalizeAggregations=false;\nINSERT INTO wikipedia\nSELECT\n TIME_PARSE(\"timestamp\") AS __time,\n *\nFROM TABLE(\n EXTERN(\n '\''{\"type\": \"http\", \"uris\": [\"https://druid.apache.org/data/wikipedia.json.gz\"]}'\'',\n '\''{\"type\": \"json\"}'\'',\n '\''[{\"name\": \"added\", \"type\": \"long\"}, {\"name\": \"channel\", \"type\": \"string\"}, {\"name\": \"cityName\", \"type\": \"string\"}, {\"name\": \"comment\", \"type\": \"string\"}, {\"name\": \"commentLength\", \"type\": \"long\"}, {\"name\": \"countryIsoCode\", \"type\": \"string\"}, {\"name\": \"countryName\", \"type\": \"string\"}, {\"name\": \"deleted\", \"type\": \"long\"}, {\"name\": \"delta\", \"type\": \"long\"}, {\"name\": \"deltaBucket\", \"type\": \"string\"}, {\"name\": \"diffUrl\", \"type\": \"string\"}, {\"name\": \"flags\", \"type\": \"string\"}, {\"name\": \"isAnonymous\", \"type\": \"string\"}, {\"name\": \"isMinor\", \"type\": \"string\"}, {\"name\": \"isNew\", \"type\": \"string\"}, {\"name\": \"isRobot\", \"type\": \"string\"}, {\"name\": \"isUnpatrolled\", \"type\": \"string\"}, {\"name\": \"metroCode\", \"type\": \"string\"}, {\"name\": \"namespace\", \"type\": \"string\"}, {\"name\": \"page\", \"type\": \"string\"}, {\"name\": \"regionIsoCode\", \"type\": \"string\"}, {\"name\": \"regionName\", \"type\": \"string\"}, {\"name\": \"timestamp\", \"type\": \"string\"}, {\"name\": \"user\", \"type\": \"string\"}]'\''\n )\n)\nPARTITIONED BY DAY"
}'
Python
import json
import requests
url = "http://ROUTER_IP:ROUTER_PORT/druid/v2/sql/task"
payload = json.dumps({
"query": "SET maxNumTasks=3;\nSET finalizeAggregations=false;\nINSERT INTO wikipedia\nSELECT\n TIME_PARSE(\"timestamp\") AS __time,\n *\nFROM TABLE(\n EXTERN(\n '{\"type\": \"http\", \"uris\": [\"https://druid.apache.org/data/wikipedia.json.gz\"]}',\n '{\"type\": \"json\"}',\n '[{\"name\": \"added\", \"type\": \"long\"}, {\"name\": \"channel\", \"type\": \"string\"}, {\"name\": \"cityName\", \"type\": \"string\"}, {\"name\": \"comment\", \"type\": \"string\"}, {\"name\": \"commentLength\", \"type\": \"long\"}, {\"name\": \"countryIsoCode\", \"type\": \"string\"}, {\"name\": \"countryName\", \"type\": \"string\"}, {\"name\": \"deleted\", \"type\": \"long\"}, {\"name\": \"delta\", \"type\": \"long\"}, {\"name\": \"deltaBucket\", \"type\": \"string\"}, {\"name\": \"diffUrl\", \"type\": \"string\"}, {\"name\": \"flags\", \"type\": \"string\"}, {\"name\": \"isAnonymous\", \"type\": \"string\"}, {\"name\": \"isMinor\", \"type\": \"string\"}, {\"name\": \"isNew\", \"type\": \"string\"}, {\"name\": \"isRobot\", \"type\": \"string\"}, {\"name\": \"isUnpatrolled\", \"type\": \"string\"}, {\"name\": \"metroCode\", \"type\": \"string\"}, {\"name\": \"namespace\", \"type\": \"string\"}, {\"name\": \"page\", \"type\": \"string\"}, {\"name\": \"regionIsoCode\", \"type\": \"string\"}, {\"name\": \"regionName\", \"type\": \"string\"}, {\"name\": \"timestamp\", \"type\": \"string\"}, {\"name\": \"user\", \"type\": \"string\"}]'\n )\n)\nPARTITIONED BY DAY"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.post(url, headers=headers, data=payload)
print(response.text)
샘플 응답
{
"taskId": "query-431c4a18-9dde-4ec8-ab82-ec7fd17d5a4e",
"state": "RUNNING"
}
응답 필드
| 필드 | 설명 |
|---|---|
| taskId | Controller 태스크 ID. Druid의 표준 Tasks API를 사용해 이 controller 태스크와 상호작용할 수 있습니다. |
| state | 쿼리의 초기 상태. |
쿼리 태스크의 상태 가져오기
쿼리 태스크의 상태를 가져옵니다. 태스크의 상태 코드, runner 상태, 태스크 타입, 데이터소스 및 기타 관련 메타데이터가 담긴 JSON 객체를 반환합니다.
URL
GET /druid/indexer/v1/task/{taskId}/status
응답
- 200 SUCCESS — 태스크 상태를 성공적으로 조회함
- 404 NOT FOUND — ID로 태스크를 찾을 수 없음
샘플 요청
다음 예시는 ID가 query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e인 태스크의 상태를 가져오는 방법을 보여줍니다.
HTTP
GET /druid/indexer/v1/task/query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e/status HTTP/1.1
Host: http://ROUTER_IP:ROUTER_PORT
cURL
curl --location --request GET 'http://ROUTER_IP:ROUTER_PORT/druid/indexer/v1/task/query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e/status'
Python
import requests
url = "http://ROUTER_IP:ROUTER_PORT/druid/indexer/v1/task/query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e/status"
payload={}
headers = {}
response = requests.post(url, headers=headers, data=payload)
print(response.text)
print(response.text)
샘플 응답
{
"task": "query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e",
"status": {
"id": "query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e",
"groupId": "query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e",
"type": "query_controller",
"createdTime": "2022-09-14T22:12:00.183Z",
"queueInsertionTime": "1970-01-01T00:00:00.000Z",
"statusCode": "RUNNING",
"status": "RUNNING",
"runnerStatusCode": "RUNNING",
"duration": -1,
"location": {
"host": "localhost",
"port": 8100,
"tlsPort": -1
},
"dataSource": "kttm_simple",
"errorMsg": null
}
}
쿼리 태스크의 리포트 가져오기
쿼리의 태스크 리포트를 가져옵니다. 리포트는 스테이지, 경고, 오류 같은 쿼리 태스크에 대한 상세 정보를 제공합니다.
태스크 API로 리포트를 볼 때는 다음을 염두에 두세요.
- 전체 작업에 대한 태스크 리포트는
query_controller태스크와 연결됩니다.query_worker태스크는 자체 리포트가 없으며, 그 정보는 controller 리포트에 포함됩니다. - 태스크가 시작되는 동안 태스크 리포트 API가 일시적으로 404 Not Found를 보고할 수 있습니다.
- 실험적 기능으로, MSQ 태스크 엔진은 SELECT 쿼리 실행을 지원합니다. SELECT 쿼리 결과는
multiStageQuery.payload.results.results태스크 리포트 키에 배열의 배열로 기록됩니다.INSERT나REPLACE없는 일반SELECT쿼리의 동작과 결과 형식은 변경될 수 있어요. multiStageQuery.payload.results.resultsTruncated는 리포트가 비대해지는 것을 막기 위해 결과가 잘렸는지 여부를 나타냅니다.- 리포트의 필드에 대한 설명은 Report response fields를 참고하세요.
URL
GET /druid/indexer/v1/task/{taskId}/reports
응답
- 200 SUCCESS — 태스크 리포트를 성공적으로 조회함
샘플 요청
다음 예시는 태스크 ID query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e인 쿼리의 리포트를 가져오는 방법을 보여줍니다.
HTTP
GET /druid/indexer/v1/task/query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e/reports HTTP/1.1
Host: http://ROUTER_IP:ROUTER_PORT
cURL
curl --location --request GET 'http://ROUTER_IP:ROUTER_PORT/druid/indexer/v1/task/query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e/reports'
Python
import requests
url = "http://ROUTER_IP:ROUTER_PORT/druid/indexer/v1/task/query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e/reports"
headers = {}
response = requests.post(url, headers=headers, data=payload)
print(response.text)
print(response.text)
샘플 응답
응답은 쿼리의 리포트 예시를 보여줍니다.
{
"multiStageQuery": {
"type": "multiStageQuery",
"taskId": "query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e",
"payload": {
"status": {
"status": "SUCCESS",
"startTime": "2022-09-14T22:12:09.266Z",
"durationMs": 28227,
"workers": {
"0": [
{
"workerId": "query-3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e-worker0_0",
"state": "SUCCESS",
"durationMs": 15511,
"pendingMs": 137
}
]
},
"pendingTasks": 0,
"runningTasks": 2,
"segmentLoadWaiterStatus": {
"state": "SUCCESS",
"dataSource": "kttm_simple",
"startTime": "2022-09-14T23:12:09.266Z",
"duration": 15,
"totalSegments": 1,
"usedSegments": 1,
"precachedSegments": 0,
"onDemandSegments": 0,
"pendingSegments": 0,
"unknownSegments": 0
},
"segmentReport": {
"shardSpec": "NumberedShardSpec",
"details": "Cannot use RangeShardSpec, RangedShardSpec only supports string CLUSTER BY keys. Using NumberedShardSpec instead."
}
},
"stages": [
{
"stageNumber": 0,
"definition": {
"id": "71ecb11e-09d7-42f8-9225-1662c8e7e121_0",
"input": [
{
"type": "external",
"inputSource": {
"type": "http",
"uris": [
"https://static.imply.io/example-data/kttm-v2/kttm-v2-2019-08-25.json.gz"
],
"httpAuthenticationUsername": null,
"httpAuthenticationPassword": null
},
"inputFormat": {
"type": "json",
"flattenSpec": null,
"featureSpec": {},
"keepNullColumns": false
},
"signature": [
{
"name": "timestamp",
"type": "STRING"
},
{
"name": "agent_category",
"type": "STRING"
},
{
"name": "agent_type",
"type": "STRING"
}
]
}
],
"processor": {
"type": "scan",
"query": {
"queryType": "scan",
"dataSource": {
"type": "inputNumber",
"inputNumber": 0
},
"intervals": {
"type": "intervals",
"intervals": [
"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
]
},
"resultFormat": "compactedList",
"columns": [
"agent_category",
"agent_type",
"timestamp"
],
"context": {
"finalize": false,
"finalizeAggregations": false,
"groupByEnableMultiValueUnnesting": false,
"scanSignature": "[{\"name\":\"agent_category\",\"type\":\"STRING\"},{\"name\":\"agent_type\",\"type\":\"STRING\"},{\"name\":\"timestamp\",\"type\":\"STRING\"}]",
"sqlInsertSegmentGranularity": "{\"type\":\"all\"}",
"sqlQueryId": "3dc0c45d-34d7-4b15-86c9-cdb2d3ebfc4e",
"sqlReplaceTimeChunks": "all"
},
"granularity": {
"type": "all"
}
}
},
"signature": [
{
"name": "__boost",
"type": "LONG"
},
{
"name": "agent_category",
"type": "STRING"
},
{
"name": "agent_type",
"type": "STRING"
},
{
"name": "timestamp",
"type": "STRING"
}
],
"shuffleSpec": {
"type": "targetSize",
"clusterBy": {
"columns": [
{
"columnName": "__boost"
}
]
},
"targetSize": 3000000
},
"maxWorkerCount": 1,
"shuffleCheckHasMultipleValues": true
},
"phase": "FINISHED",
"workerCount": 1,
"partitionCount": 1,
"startTime": "2022-09-14T22:12:11.663Z",
"duration": 19965,
"sort": true
},
{
"stageNumber": 1,
"definition": {
"id": "71ecb11e-09d7-42f8-9225-1662c8e7e121_1",
"input": [
{
"type": "stage",
"stage": 0
}
],
"processor": {
"type": "segmentGenerator",
"dataSchema": {
"dataSource": "kttm_simple",
"timestampSpec": {
"column": "__time",
"format": "millis",
"missingValue": null
},
"dimensionsSpec": {
"dimensions": [
{
"type": "string",
"name": "timestamp",
"multiValueHandling": "SORTED_ARRAY",
"createBitmapIndex": true
},
{
"type": "string",
"name": "agent_category",
"multiValueHandling": "SORTED_ARRAY",
"createBitmapIndex": true
},
{
"type": "string",
"name": "agent_type",
"multiValueHandling": "SORTED_ARRAY",
"createBitmapIndex": true
}
],
"dimensionExclusions": [
"__time"
],
"includeAllDimensions": false
},
"metricsSpec": [],
"granularitySpec": {
"type": "arbitrary",
"queryGranularity": {
"type": "none"
},
"rollup": false,
"intervals": [
"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
]
},
"transformSpec": {
"filter": null,
"transforms": []
}
},
"columnMappings": [
{
"queryColumn": "timestamp",
"outputColumn": "timestamp"
},
{
"queryColumn": "agent_category",
"outputColumn": "agent_category"
},
{
"queryColumn": "agent_type",
"outputColumn": "agent_type"
}
],
"tuningConfig": {
"maxNumWorkers": 1,
"maxRowsInMemory": 100000,
"rowsPerSegment": 3000000
}
},
"signature": [],
"maxWorkerCount": 1
},
"phase": "FINISHED",
"workerCount": 1,
"partitionCount": 1,
"startTime": "2022-09-14T22:12:31.602Z",
"duration": 5891
}
],
"counters": {
"0": {
"0": {
"input0": {
"type": "channel",
"rows": [
465346
],
"files": [
1
],
"totalFiles": [
1
]
},
"output": {
"type": "channel",
"rows": [
465346
],
"bytes": [
43694447
],
"frames": [
7
]
},
"shuffle": {
"type": "channel",
"rows": [
465346
],
"bytes": [
41835307
],
"frames": [
73
]
},
"sortProgress": {
"type": "sortProgress",
"totalMergingLevels": 3,
"levelToTotalBatches": {
"0": 1,
"1": 1,
"2": 1
},
"levelToMergedBatches": {
"0": 1,
"1": 1,
"2": 1
},
"totalMergersForUltimateLevel": 1,
"progressDigest": 1
}
}
},
"1": {
"0": {
"input0": {
"type": "channel",
"rows": [
465346
],
"bytes": [
41835307
],
"frames": [
73
]
},
"segmentGenerationProgress": {
"type": "segmentGenerationProgress",
"rowsProcessed": 465346,
"rowsPersisted": 465346,
"rowsMerged": 465346
}
}
}
}
}
}
}
다음 표는 /druid/indexer/v1/task/{taskId}/reports 엔드포인트로 MSQ 태스크 엔진용 리포트를 가져올 때의 응답 필드를 설명합니다.
| 필드 | 설명 |
|---|---|
| multiStageQuery.taskId | Controller 태스크 ID. |
| multiStageQuery.payload.status | 쿼리 상태 컨테이너. |
| multiStageQuery.payload.status.status | RUNNING, SUCCESS, 또는 FAILED. |
| multiStageQuery.payload.status.startTime | ISO 형식의 쿼리 시작 시간. 쿼리가 실행을 시작했을 때만 존재합니다. |
| multiStageQuery.payload.status.durationMs | 쿼리가 실행을 시작한 후 경과한 밀리초. -1은 쿼리가 아직 시작되지 않았음을 뜻합니다. |
| multiStageQuery.payload.status.workers | controller 태스크의 워커. |
| multiStageQuery.payload.status.workers. |
재시도를 포함한 워커 태스크 배열. |
| multiStageQuery.payload.status.workers. |
워커 태스크의 ID. |
| multiStageQuery.payload.status.workers. |
RUNNING, SUCCESS, 또는 FAILED. |
| multiStageQuery.payload.status.workers. |
워커 태스크가 처음 요청된 시점과 완료된 시점 사이의 경과 밀리초. 상태가 RUNNING인 워커 태스크에서는 -1입니다. |
| multiStageQuery.payload.status.workers. |
워커 태스크가 처음 요청된 시점과 완전히 RUNNING이 된 시점 사이의 경과 밀리초. 실제 작업 시간은 actualWorkTimeMS = durationMs - pendingMs로 계산할 수 있습니다. |
| multiStageQuery.payload.status.pendingTasks | 완전히 시작되지 않은 태스크 수. -1은 현재 그 수를 알 수 없음을 뜻합니다. |
| multiStageQuery.payload.status.runningTasks | 현재 실행 중인 태스크 수. controller가 포함되므로 최소 1이어야 합니다. |
| multiStageQuery.payload.status.segmentLoadStatus | 세그먼트 로딩 컨테이너. 세그먼트가 게시된 후에만 존재합니다. |
| multiStageQuery.payload.status.segmentLoadStatus.state | INIT, WAITING, SUCCESS, FAILED 또는 TIMED_OUT 중 하나. |
| multiStageQuery.payload.status.segmentLoadStatus.startTime | controller가 세그먼트가 로딩을 끝내기를 기다린 시점 이후의 시간. |
| multiStageQuery.payload.status.segmentLoadStatus.duration | controller가 세그먼트가 로드되기를 기다린 밀리초 단위 기간. |
| multiStageQuery.payload.status.segmentLoadStatus.totalSegments | 작업이 생성한 총 세그먼트 수. tombstone 세그먼트(있다면)를 포함합니다. |
| multiStageQuery.payload.status.segmentLoadStatus.usedSegments | 로드 규칙에 따라 used로 표시된 세그먼트 수. unused 세그먼트는 언제든 정리될 수 있습니다. |
| multiStageQuery.payload.status.segmentLoadStatus.precachedSegments | 로드 규칙에 따라 precached로 표시되고 historical이 서비스하는 세그먼트 수. |
| multiStageQuery.payload.status.segmentLoadStatus.onDemandSegments | 로드 규칙에 따라 어떤 historical에도 로드되지 않은 세그먼트 수. |
| multiStageQuery.payload.status.segmentLoadStatus.pendingSegments | 로드할 남은 세그먼트 수. |
| multiStageQuery.payload.status.segmentLoadStatus.unknownSegments | 상태가 알려지지 않은 세그먼트 수. |
| multiStageQuery.payload.status.segmentReport | 세그먼트 리포트. 쿼리가 수집일 때만 존재합니다. |
| multiStageQuery.payload.status.segmentReport.shardSpec | 선택된 shard spec을 담습니다. |
| multiStageQuery.payload.status.segmentReport.details | 선택된 shard spec에 대한 추가 근거를 담습니다. |
| multiStageQuery.payload.status.errorReport | 오류 객체. 오류가 있었을 때만 존재합니다. |
| multiStageQuery.payload.status.errorReport.taskId | 오류를 보고한 태스크(알려진 경우). controller 태스크일 수도 워커 태스크일 수도 있습니다. |
| multiStageQuery.payload.status.errorReport.host | 오류를 보고한 태스크의 호스트네임과 포트(알려진 경우). |
| multiStageQuery.payload.status.errorReport.stageNumber | 오류가 특정 스테이지 실행 중 발생했다면 그 스테이지 번호. |
| multiStageQuery.payload.status.errorReport.error | 오류 코드 테이블에 설명된 대로 errorCode를 최소한 포함하고 다른 필드도 포함할 수 있는 오류 객체. 오류가 있으면 항상 존재합니다. |
| multiStageQuery.payload.status.errorReport.error.errorCode | 오류 코드 테이블의 오류 코드 중 하나. 오류가 있으면 항상 존재합니다. |
| multiStageQuery.payload.status.errorReport.error.errorMessage | 사용자 친화적인 오류 메시지. 오류가 있어도 항상 존재하는 것은 아닙니다. |
| multiStageQuery.payload.status.errorReport.exceptionStackTrace | 오류가 서버 측 예외 때문이었다면 문자열 형태의 Java 스택 트레이스. |
| multiStageQuery.payload.stages | 쿼리 스테이지 배열. |
| multiStageQuery.payload.stages[].stageNumber | 각 스테이지는 다른 스테이지와 구분하는 번호를 가집니다. |
| multiStageQuery.payload.stages[].phase | NEW, READING_INPUT, POST_READING, RESULTS_COMPLETE, 또는 FAILED. 스테이지가 시작했을 때만 존재합니다. |
| multiStageQuery.payload.stages[].workerCount | 이 스테이지가 실행되는 병렬 태스크 수. 스테이지가 시작했을 때만 존재합니다. |
| multiStageQuery.payload.stages[].partitionCount | 이 스테이지가 생성한 출력 파티션 수. 스테이지가 시작하고 출력 파티션 수를 계산했을 때만 존재합니다. |
| multiStageQuery.payload.stages[].startTime | 이 스테이지의 시작 시간. 스테이지가 시작했을 때만 존재합니다. |
| multiStageQuery.payload.stages[].duration | 스테이지가 실행된 밀리초 수. 스테이지가 시작했을 때만 존재합니다. |
| multiStageQuery.payload.stages[].sort | 스테이지가 실행의 일부로 정렬을 수행하면 true로 설정되는 boolean. |
| multiStageQuery.payload.stages[].definition | 스테이지가 무엇을 하는지 정의하는 객체. |
| multiStageQuery.payload.stages[].definition.id | 스테이지의 고유 식별자. |
| multiStageQuery.payload.stages[].definition.input | 스테이지가 가진 입력 배열. |
| multiStageQuery.payload.stages[].definition.broadcast | 브로드캐스트되는 입력 인덱스 배열. 브로드캐스트되는 입력이 있을 때만 존재합니다. |
| multiStageQuery.payload.stages[].definition.processor | 프로세서 로직을 정의하는 객체. |
| multiStageQuery.payload.stages[].definition.signature | 스테이지의 출력 시그니처. |
쿼리 태스크 취소
쿼리 태스크를 취소합니다. 성공적으로 취소된 태스크의 ID가 담긴 JSON 객체를 반환합니다.
URL
POST /druid/indexer/v1/task/{taskId}/shutdown
응답
- 200 SUCCESS — 태스크를 성공적으로 종료함
- 404 NOT FOUND — ID로 태스크를 찾을 수 없거나 태스크가 더 이상 실행 중이 아님
샘플 요청
다음 예시는 ID가 query-655efe33-781a-4c50-ae84-c2911b42d63c인 쿼리 태스크를 취소하는 방법을 보여줍니다.
HTTP
POST /druid/indexer/v1/task/query-655efe33-781a-4c50-ae84-c2911b42d63c/shutdown HTTP/1.1
Host: http://ROUTER_IP:ROUTER_PORT
cURL
curl --location --request POST 'http://ROUTER_IP:ROUTER_PORT/druid/indexer/v1/task/query-655efe33-781a-4c50-ae84-c2911b42d63c/shutdown'
Python
import requests
url = "http://ROUTER_IP:ROUTER_PORT/druid/indexer/v1/task/query-655efe33-781a-4c50-ae84-c2911b42d63c/shutdown"
payload = {}
headers = {}
response = requests.post(url, headers=headers, data=payload)
print(response.text)
print(response.text)
샘플 응답
응답은 취소된 태스크의 ID를 보여줍니다.
{
"task": "query-655efe33-781a-4c50-ae84-c2911b42d63c"
}
더 알아보기 (Learn more)
- MSQ 태스크 엔진에 대한 자세한 내용은 multi-stage query 문서를 참고하세요.
- SQL 기반 수집의 전체 문법은 SQL-based ingestion 문서를 확인해 보세요.