이야기박스
Elasticsearch - RestHighLevelClient를 통하여 대량의 문서를 조회하기 본문
Elasticsearch - RestHighLevelClient를 통하여 대량의 문서를 조회하기
박스님 2022. 5. 18. 18:18
Elasticsearch에서 대량의 문서를 조회하려고 하였는데, 최대 10,000건 이상의 문서는 조회되지 않는 현상이 발생하였습니다. 오늘은 Elasticsearch의 Java 라이브러리를 이용하여 10,000건 이상의 로그를 조회하는 방법을 포스팅해보려고 합니다.
원인
ES에서의 설정 값 'index.max_result_window'(default 10,000건) 만큼의 결과만 hits으로 노출되고 있었습니다.
해결 방안
1. index.max_result_window 값 증가
2. Scroll API
3. Search After
1번은 근본적인 해결 방안이 아니기 때문에 제외하고, 나머지 2-3번 방법을 위주로 조사해보았습니다.
마침 공식 문서 가보니, Scroll API가 아닌 Search After 사용을 권장하고 있었고 이를 사용하기로 하였습니다.
We no longer recommend using the scroll API for deep pagination. If you need to preserve the index state while paging through more than 10,000 hits, use the search_after parameter with a point in time (PIT).
방법
SearchAfter는 "동일한 쿼리를 여러번 반복하여 조회하는 방식" 으로 요약할 수 있을 것 같습니다.
ES Search에서 정렬을 하고 조회를 하게 되면, hit 값에 sortValues를 반환하게 되는데, 이 값을 이용하여 가장 마지막으로 조회한 문서의 다음 값을 다시 찾게 됩니다.
이 때 중요한 점은, PIT (Point In Time) 값을 함께 설정해주어 동일한 시점에 검색을 한 것과 같은 효과를 내주어야 한다는 것입니다.
구현
REST API의 예시는 많은데, Java 라이브러리를 활용한 예시는 많지 않았습니다. 마침 하나의 블로그를 발견하였고, 이를 참고하여 아래 코드를 작성하였습니다.
// 메모장으로 작업한 것이라 오타가 있을 수 있음.
Object[] searchAfter = null;
while (true) {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(queryBuilder)
.from(pageNumber * pageSize)
.size(pageSize)
.sort(SortBuilders.fieldSort("@timestamp").order(SortOrder.ASC))
.trackTotalHits(true)
.pointInTimeBuilder(new PointInTimeBuilder("storyparks-examples"))
.timeout(new TimeValue(searchSourceBuilderTimeout, TimeUnit.SECONDS));
if (searchAfter != null) {
searchSourceBuilder.searchAfter(searchAfter);
}
SearchRequest searchRequest = new SearchRequest(indexPattern);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits[] hits = searchResponse.getHits().getHits();
if (hits.length > 0) {
SearchHit lastHitDocument = hits[hits.length - 1];
searchAfter = lastHitDocument.getSortValues();
} else {
break;
}
}
기타 잡설
'track_total_hits' 옵션을 사용하면 10,000건이 넘는 로그를 조회 할 수 있을 지 알았는데, 자세히 다시 읽어보니 아닌 듯 합니다.
If true, the exact number of hits is returned at the cost of some performance. If false, the response does not include the total number of hits matching the query.
실제 로그를 반환하는 것이 아니라, 로그의 갯수만 반환하는 것으로 보입니다.
Reference
'Computer & Data > Big Data' 카테고리의 다른 글
Redis High Availability; Sentinel vs Cluster (4) | 2022.08.20 |
---|---|
What is Redis; Remote Dictionary Server (0) | 2022.08.20 |
Streaming 비교, Spark Streaming - Flink Streaming (0) | 2022.03.24 |
Hive 및 Metastore 버전간 호환성 체크 (2.3.2, 3.1.2) (0) | 2022.03.20 |
Logstash를 활용하여 rsyslog를 받아보자 (0) | 2022.03.09 |