Scroll API

Scroll API

scroll 작업을 사용하면 대량의 결과를 검색할 수 있어요. 예를 들어 머신러닝 작업에서는 배치 단위로 제한 없는 수의 결과를 요청할 수 있죠.

도입 버전 1.0

scroll 작업을 사용하려면 검색 컨텍스트와 함께 요청 헤더에 scroll 파라미터를 추가해서, 스크롤을 얼마나 오래 유지해야 하는지 OpenSearch에 알려줘요. 이 검색 컨텍스트는 결과 한 배치를 처리하기에 충분히 길어야 해요.

검색 컨텍스트는 메모리를 많이 소모하므로, 빈번한 사용자 쿼리에는 scroll 작업을 사용하지 않는 것이 좋아요. 대신 사용자 쿼리에는 search_after 파라미터와 함께 sort 파라미터를 사용해서 응답을 스크롤하세요.

다음 성능 고려 사항을 기억하세요:

  • 관련성 점수가 필요 없을 때 가장 효율적으로 스크롤하려면 _doc로 정렬하세요. 이렇게 하면 점수 계산이 꺼지고 문서가 자연스러운 인덱스 순서로 반환돼요. 이 방식은 인덱스의 모든 문서를 반복하는 가장 빠른 방법이에요.
  • 집계 결과는 최초 검색 응답에만 포함돼요. 이후의 스크롤 요청은 다음 배치의 결과(hits)만 반환해요.
  • 열려 있는 각 스크롤 컨텍스트는 연결된 샤드의 세그먼트 병합을 막고, 파일 핸들과 힙 메모리를 소모해요. 더 이상 필요하지 않으면 스크롤 컨텍스트를 즉시 닫으세요.
  • 열려 있는 스크롤 컨텍스트의 최대 개수는 search.max_open_scroll_context 클러스터 설정으로 제어되며 기본값은 500이에요.

엔드포인트

GET  /_search/scroll
POST /_search/scroll
GET  /_search/scroll/{scroll_id}
POST /_search/scroll/{scroll_id}

경로 파라미터

다음 표는 사용 가능한 경로 파라미터를 보여줘요. 모든 경로 파라미터는 선택 사항이에요.

파라미터 데이터 타입 설명
scroll_id String 검색의 스크롤 ID예요. 스크롤 ID는 매우 길 수 있으므로 요청 본문에 지정하는 것을 권장해요.

쿼리 파라미터

다음 표는 사용 가능한 쿼리 파라미터를 보여줘요. 모든 쿼리 파라미터는 선택 사항이에요.

파라미터 데이터 타입 설명 기본값
scroll String 검색 컨텍스트를 연장할 시간이에요. 이 값은 최초 검색 요청의 scroll 파라미터에 설정된 시간을 덮어써요. search.max_keep_alive 클러스터 설정을 초과할 수 없어요. 없음
scroll_id String 검색의 스크롤 ID예요. 스크롤 ID는 매우 길 수 있으므로 쿼리 파라미터보다는 요청 본문에 지정하는 것을 권장해요. 없음
rest_total_hits_as_int Boolean hits.total 속성을 정수( true )로 반환할지 객체( false )로 반환할지 여부예요. false

요청 본문 필드

다음 표는 사용 가능한 요청 본문 필드를 보여줘요.

필드 데이터 타입 설명
scroll String 다음 스크롤 요청을 위해 검색 컨텍스트를 연장할 시간이에요. 쿼리 파라미터와 요청 본문 필드가 모두 지정되면 쿼리 파라미터가 우선해요.
scroll_id String 필수. 최초 검색 요청이나 이전 스크롤 요청이 반환한 스크롤 ID예요.

예제 요청

다음 예제는 스크롤 작업을 시작하는 것부터 모든 결과를 가져오는 과정까지의 워크플로를 보여줘요.

1단계: 스크롤 작업 시작

스크롤을 시작하려면 검색 컨텍스트를 유지할 시간(예: 10분이면 10m)을 지정한 scroll 파라미터와 함께 최초 검색 쿼리를 보내요. size 파라미터로 각 배치에서 반환할 결과 수를 설정해요:

GET /shakespeare/_search?scroll=10m
{
  "size": 10000
}

OpenSearch는 결과를 캐시하고, 배치 단위로 접근할 수 있는 스크롤 ID를 반환해요:


"_scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAUWdmpUZDhnRFBUcWFtV21nMmFwUGJEQQ=="

2단계: 이후 배치 검색

다음 결과 배치를 받으려면 이 스크롤 ID를 scroll 작업에 전달해요:

GET /_search/scroll
{
  "scroll": "10m",
  "scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAUWdmpUZDhnRFBUcWFtV21nMmFwUGJEQQ=="
}

이 스크롤 ID로 검색 컨텍스트가 열려 있는 동안 10,000개씩 배치로 결과를 받을 수 있어요. 보통 스크롤 ID는 요청 사이에 변하지 않지만, 변할 수 있으므로 항상 최신 스크롤 ID를 사용해야 해요. 설정된 검색 컨텍스트 내에 다음 스크롤 요청을 보내지 않으면 scroll 작업은 결과를 반환하지 않아요.

결과의 끝 감지

모든 결과를 스크롤했다면 마지막 배치에 빈 hits 배열이 들어 있어요:

{
  "_scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAUWdmpUZDhnRFBUcWFtV21nMmFwUGJEQQ==",
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 10000,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  }
}

hits.hits가 빈 배열이면 사용 가능한 모든 결과를 검색한 것이므로 스크롤을 중지해야 해요. 리소스를 확보하기 위해 스크롤 컨텍스트를 닫아야 해요.

슬라이스드 스크롤 사용

수십억 개의 결과가 예상된다면 슬라이스드 스크롤(sliced scroll)을 사용하세요. 슬라이싱을 사용하면 같은 요청에 대해 여러 스크롤 작업을 병렬로 수행할 수 있어요. 스크롤의 ID와 최대 슬라이스 수를 설정해요:

GET /shakespeare/_search?scroll=10m
{
  "slice": {
    "id": 0,
    "max": 10
  },
  "query": {
    "match_all": {}
  }
}

각 슬라이스는 독립적인 고유 스크롤 ID를 생성해요. "max": 10이면 10개의 별도 스크롤 작업(ID 0~9)을 시작하며, 각각 데이터의 서로 다른 하위 집합을 반환해요. 그런 다음 모든 슬라이스가 소진될 때까지 각 슬라이스를 독립적으로 스크롤해요. 슬라이스 수는 index.max_slices_per_scroll 설정으로 제한되며 기본값은 1024예요.

3단계: 스크롤 컨텍스트 닫기

scroll 작업은 타임아웃까지 계속 컴퓨팅 리소스를 소모하므로 스크롤을 마친 후에는 검색 컨텍스트를 닫아요:

DELETE /_search/scroll/DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAcWdmpUZDhnRFBUcWFtV21nMmFwUGJEQQ==

열려 있는 모든 스크롤 컨텍스트를 닫으려면:

DELETE /_search/scroll/_all

스크롤 검색 결과는 최초 검색 요청 시점의 인덱스 상태를 반영해요. 스크롤이 시작된 후에 인덱싱되거나 수정된 문서는 쿼리와 일치하더라도 스크롤 결과에 나타나지 않아요.

예제 응답

scroll 작업은 _scroll_id, hits, _shards, 타이밍 정보를 포함해 search API와 동일한 응답 구조를 반환해요.

clear scroll 작업은 다음 응답을 반환해요:

{
  "succeeded": true,
  "num_freed": 1
}

응답 본문 필드

다음 표는 scroll 작업의 응답 본문 필드를 보여줘요.

필드 데이터 타입 설명
_scroll_id String 다음 스크롤 요청에 사용할 스크롤 ID예요. 이 값은 요청 사이에 변할 수 있으므로 항상 가장 최근에 반환된 ID를 사용해요.
took Integer 요청이 완료되는 데 걸린 시간(밀리초)이에요.
timed_out Boolean 요청이 완료되기 전에 타임아웃되었는지 여부예요.
_shards Object 관련된 샤드에 대한 정보로, total , successful , skipped , failed 개수를 포함해요.
hits Object 전체 hit 수와 일치하는 문서 배열을 포함한 검색 결과예요. 스크롤이 완료되면 hits.hits는 빈 배열이에요.

다음 표는 clear scroll 작업의 응답 본문 필드를 보여줘요.

필드 데이터 타입 설명
succeeded Boolean 스크롤 컨텍스트가 성공적으로 해제되었는지 여부예요.
num_freed Integer 해제된 스크롤 컨텍스트 수예요.

필요한 권한

Security 플러그인을 사용한다면 적절한 권한이 있는지 확인하세요: indices:data/read/scroll 및 indices:data/read/scroll/clear.

관련 문서

출처: 문서