딥 스토리지에서 쿼리하기

딥 스토리지에서 쿼리하기 (Tutorial: Query from deep storage)

Query from deep storage 기능을 사용하면 딥 스토리지(deep storage)에만 저장된 세그먼트를 쿼리할 수 있어요. 모든 데이터를 Historical 프로세스에 로드하는 것보다 비용이 낮아지는데, 그 대가로 딥 스토리지 쿼리는 완료되는 데 더 오래 걸릴 수 있어요. 이 튜토리얼에서는 예제 데이터를 로드하고, 일부 세그먼트가 Historical 서비스에 로드되지 않도록 로드 규칙을 구성한 뒤 딥 스토리지에서 데이터를 쿼리하는 과정을 진행해요.

출처: 문서

본문

중앙 집중식 데이터소스 스키마 (centralized datasource schema)를 활성화했다면, Historical에 사용 가능한 세그먼트가 전혀 없어도 딥 스토리지에만 있는 데이터소스를 쿼리할 수 있어요.

이 튜토리얼의 쿼리를 실행할 때는 ROUTER:PORT 를 Router 프로세스의 위치와 포트 번호로 바꿔 주세요. 예를 들어 quickstart 배포에는 localhost:8888 을 사용해 주세요.

더 일반적인 정보는 Query from deep storage를 참고해 주세요.

기존 클러스터에서 이 기능을 시도한다면, query from deep storage의 사전 요구 사항이 충족되는지 확인해 주세요.

예제 데이터 로드하기 (Load example data)

Load data 마법사 또는 다음 SQL 쿼리를 사용해 Druid에 번들된 wikipedia 샘플 데이터소스를 수집해 주세요. 마법사를 사용한다면 파티셔닝을 시간(hour) 단위로 변경해야 해요.

시간별 파티셔닝은 세그먼트 granularity를 더 세밀하게 만들어서, 세그먼트를 선택적으로 Historical에 로드하거나 딥 스토리지에 유지할 수 있게 해 줘요.

쿼리 보기 (Show the query)

REPLACE INTO "wikipedia" OVERWRITE ALL
WITH "ext" AS (SELECT *
FROM TABLE(
  EXTERN(
    '{"type":"http","uris":["https://druid.apache.org/data/wikipedia.json.gz"]}',
    '{"type":"json"}'
  ))
  EXTEND ("isRobot" VARCHAR, "channel" VARCHAR, "timestamp" VARCHAR, "flags" VARCHAR, "isUnpatrolled" VARCHAR, "page" VARCHAR, "diffUrl" VARCHAR, "added" BIGINT, "comment" VARCHAR, "commentLength" BIGINT, "isNew" VARCHAR, "isMinor" VARCHAR, "delta" BIGINT, "isAnonymous" VARCHAR, "user" VARCHAR, "deltaBucket" BIGINT, "deleted" BIGINT, "namespace" VARCHAR, "cityName" VARCHAR, "countryName" VARCHAR, "regionIsoCode" VARCHAR, "metroCode" BIGINT, "countryIsoCode" VARCHAR, "regionName" VARCHAR))
SELECT
  TIME_PARSE("timestamp") AS "__time",
  "isRobot",
  "channel",
  "flags",
  "isUnpatrolled",
  "page",
  "diffUrl",
  "added",
  "comment",
  "commentLength",
  "isNew",
  "isMinor",
  "delta",
  "isAnonymous",
  "user",
  "deltaBucket",
  "deleted",
  "namespace",
  "cityName",
  "countryName",
  "regionIsoCode",
  "metroCode",
  "countryIsoCode",
  "regionName"
FROM "ext"
PARTITIONED BY HOUR

로드 규칙 구성하기 (Configure a load rule)

로드 규칙은 다음 구간에 속하는 모든 세그먼트를 딥 스토리지에만 유지하도록 Druid를 구성해요:

2016-06-27T00:00:00.000Z/2016-06-27T02:59:00.000Z

규칙의 JSON 형태는 다음과 같아요:

[
  {
    "interval": "2016-06-27T00:00:00.000Z/2016-06-27T02:59:00.000Z",
    "tieredReplicants": {},
    "useDefaultTierForNull": false,
    "type": "loadByInterval"
  }
]

나머지 세그먼트는 클러스터의 기본 로드 규칙을 사용해요. quickstart의 경우 그건 나머지 모든 세그먼트가 Historical 프로세스에 로드된다는 뜻이에요.

로드 규칙은 API 또는 Druid 콘솔을 통해 구성할 수 있어요. Druid 콘솔로 구성하려면 Datasources > Actions 컬럼의 ... > Edit retention rules 로 이동한 뒤, 제공된 JSON을 JSON 탭에 붙여 넣어 주세요.

복제 계수 확인하기 (Verify the replication factor)

딥 스토리지에서만 사용할 수 있는 세그먼트는 Druid 시스템 테이블에서 replication_factor 가 0이에요. 다음 쿼리로 로드 규칙이 의도대로 동작했는지 확인할 수 있어요:

SELECT "segment_id", "replication_factor", "num_replicas" 
FROM sys."segments" WHERE datasource = 'wikipedia'

Druid 콘솔의 Segments 뷰에서 Replication factor 컬럼을 확인해서도 검증할 수 있어요.

Druid가 보존 규칙을 처리하는 동안 복제본 수와 복제 계수가 일시적으로 다를 수 있다는 점에 주의해 주세요.

딥 스토리지에서 쿼리하기 (Query from deep storage)

이제 딥 스토리지에서만 사용할 수 있는 세그먼트가 생겼으니, 다음 쿼리를 실행해 보세요:

SELECT page FROM wikipedia WHERE __time < 
TIMESTAMP'2016-06-27 00:10:00' LIMIT 10

이 쿼리를 비동기적으로 실행하려면 쿼리 컨텍스트에서 ASYNC 실행 모드를 지정해 주세요. 쿼리 앞에 SET 문으로 쿼리 컨텍스트 파라미터를 적용해 주세요.

예를 들어 다음 curl 명령을 실행해 주세요:

curl --location 'http://localhost:8888/druid/v2/sql/statements' \
--header 'Content-Type: application/json' \
--data '{
  "query": "SET executionMode = '\''ASYNC'\''; SELECT page FROM wikipedia WHERE __time < TIMESTAMP '\''2016-06-27 00:10:00'\'' LIMIT 10"
}'

이 쿼리는 00:10:00 보다 앞선 타임스탬프를 가진 레코드를 찾아요. 앞서 구성한 로드 규칙에 따라 이 데이터는 딥 스토리지에서만 사용할 수 있어요.

API를 통해 딥 스토리지 쿼리를 제출하면 다음 응답을 받아요:

응답 보기 (Show the response)

{
    "queryId": "query-6888b6f6-e597-456c-9004-222b05b97051",
    "state": "ACCEPTED",
    "createdAt": "2023-07-28T21:59:02.334Z",
    "schema": [
        {
            "name": "page",
            "type": "VARCHAR",
            "nativeType": "STRING"
        }
    ],
    "durationMs": -1
}

queryID 를 반드시 기록해 두세요. 쿼리와 상호작용할 때 필요해요.

이를 Druid SQL의 일반 엔드포인트인 POST /sql 에 쿼리를 제출하는 경우와 비교해 보세요:

curl --location 'http://localhost:8888/druid/v2/sql/' \
--header 'Content-Type: application/json' \
--data '{
  "query": "SET executionMode = '\''ASYNC'\''; SELECT page FROM wikipedia WHERE __time < TIMESTAMP '\''2016-06-27 00:10:00'\'' LIMIT 10"
}'

반환받는 응답은 빈 응답이에요. 쿼리와 일치하는 레코드가 Historical에 없기 때문이에요.

쿼리 상태 가져오기 (Get query status)

:queryId 를 쿼리의 ID로 바꾸고 다음 curl 명령을 실행해 쿼리 상태를 가져와 주세요:

curl --location --request GET 'http://localhost:8888/druid/v2/sql/statements/:queryId' \
--header 'Content-Type: application/json' \

실행 중 쿼리의 응답 (Response for a running query)

실행 중 쿼리의 응답은 쿼리를 제출했을 때의 응답과 같지만, 상태가 ACCEPTED 대신 RUNNING 이에요.

완료된 쿼리의 응답 (Response for a completed query)

성공한 쿼리는 페이지 번호(id), 페이지당 행 수(numRows), 페이지 크기(sizeInBytes)를 포함하는 pages 객체도 반환해요. 결과를 가져올 때 페이지 번호를 파라미터로 전달하면 얻는 결과를 다듬을 수 있어요.

sampleRecords 는 간결함을 위해 잘렸다는 점에 유의해 주세요.

응답 보기 (Show the response)

{
    "queryId": "query-6888b6f6-e597-456c-9004-222b05b97051",
    "state": "SUCCESS",
    "createdAt": "2023-07-28T21:59:02.334Z",
    "schema": [
        {
            "name": "page",
            "type": "VARCHAR",
            "nativeType": "STRING"
        }
    ],
    "durationMs": 87351,
    "result": {
        "numTotalRows": 152,
        "totalSizeInBytes": 9036,
        "dataSource": "__query_select",
        "sampleRecords": [
            [
                "Salo Toraut"
            ],
            [
                "利用者:ワーナー成増/放送ウーマン賞"
            ],
            [
                "Bailando 2015"
            ],
            ...
            ...
            ...
        ],
        "pages": [
            {
                "id": 0,
                "numRows": 152,
                "sizeInBytes": 9036
            }
        ]
    }
}

쿼리 결과 가져오기 (Get query results)

:queryId 를 쿼리의 ID로 바꾸고 다음 curl 명령을 실행해 쿼리 결과를 가져와 주세요:

curl --location 'http://ROUTER:PORT/druid/v2/sql/statements/:queryId'

응답이 간결함을 위해 잘렸다는 점에 유의해 주세요.

응답 보기 (Show the response)

[
    {
        "page": "Salo Toraut"
    },
    {
        "page": "利用者:ワーナー成増/放送ウーマン賞"
    },
    {
        "page": "Bailando 2015"
    },
    ...
    ...
    ...
]

더 읽어보기 (Further reading)

더 알아보기 (Learn more)