////
Search
Duplicate
🕚

11장. 검색 성능 최적화

ElasticSearch 캐시의 종류와 특성
검색 쿼리 튜닝하기
샤드 배치 결정하기
forcemerge API 활용하기
그 외의 검색 성능을 확보하는 방법들

11.1 ElasticSearch 캐시의 종류와 특성

: ElasticSearch로 요청되는 다양한 검색 쿼리는 동일한 결과에 대해 좀더 빠른 응답을 제공하기 위해 쿼리의 결과를 메모리에 저장
11.1.1 Node Query Cache
: filter context에 의해 검색된 문서의 결과가 캐싱되는 곳
: filter context로 호출한 적이 있는 문서를 bitset을 1로 설정하여 사용자가 호출한 적이 있다는 것을 문서에 표시
: ElasticSearch는 문서별로 bitset을 설정하면서 사용자의 쿼리 횟수와 bitset이 1인 문서들 간의 연관 관계를 지속적으로 확인, 자주 호출되었다고 판단한 것들을 캐싱
: 많은 문서가 캐싱되어 허용된 캐시 메모리를 초과할 경우, LRU 알고리즘에 의해 캐싱된 문서를 삭제
11.1.2 Shard Request Cache
: Node Query Cache가 노드에 할당된 캐시 영역이라면 Shard Request Cache는 샤드를 대상으로 캐싱되는 영역
: 특정 필드에 대한 검색이기 때문에 전체 샤드에 캐싱되며 기본적으로 ElasticSearch 클러스터에 활성화되어 있는 캐시
: Node Query Cache가 검색 엔진에서 활용하기 적합한 캐시 영역이라면 Shard Request Cache는 분석 엔진에서 활용하기 적합한 캐시 영역, 다만 이 영역은 Refresh 시 사라짐
11.1.3 Field Data Cache
: 주로 검색 결과를 정렬하거나 집계 쿼리를 수행할 때 지정한 필드만을 대상으로 해당 필드의 모든 데이터를 메모리에 저장하는 캐싱 영역
: 집계를 수행한 필드의 모든 데이터를 메모리에 적재하기 때문에 집계 시에 불러들일 데이터의 양을 고려하여 사용해야 한다.

11.2 검색 쿼리 튜닝하기

: 검색 성능을 떨어트리는 요인 중 하나는 너무 많은 필드를 사용하는 것, 검색 쿼리를 작성하다보면 많은 필드를 하나의 필드로 검색할 수 있는 기능이 copy_to
curl -X PUT "localhost:9200/copyto_index/_doc/_mapping?pretty" -H 'Content-Type: application/json' -d' { "_doc": { "properties": { "first_name": { "type": "text", "copy_to": "full_name" }, "last_name": { "type": "text", "copy_to": "full_name" }, "full_name": { "type": "text" } } } }
JSON
복사
: match 쿼리는 Query Context에 속하는 쿼리로 분석을 위한 추가 시간이 필요, 반면에 Filter Context에 속하는 term 쿼리는 검색어를 분석하지 않아 더 빠름
: ElasticSearch에서는 수치 계산이 없는 숫자형 데이터는 keyword 필드 데이터 타입으로 매핑하도록 권고
: 회원의 고유번호나 계좌번호 같은 숫자형 데이터는 연산이 필요 없음, 이러한 데이터는 주로 정확하게 일치하는 문서를 찾는 쿼리를 사용하므로 term 쿼리가 적합

11.3 샤드 배치 결정하기

데이터 노드 간 디스크 사용량 불균형
색인/검색 성능 부족
데이터 노드 증설 후에도 검색 성능이 나아지지 않음
클러스터 전체의 샤드 개수가 지나치게 많음

11.4 forcemerge API

: 샤드에 여러 개의 세그먼트가 있다면 해당 세그먼트들이 모두 검색 요청에 응답을 주어야함, 쿼리마다 많은 세그먼트에 접근해야 한다면 이는 곧 성능 저하로 이어진다.
: forcemerge API는 이렇게 세그먼트를 강제로 병합할 때, 사용하는 API
: 하나의 세그먼트로 병합된 인덱스는 검색 시 훨씬 적은 파일에 접근하게 된다.
: 클러스터의 특성에 맞게 샤드 계획을 잘 수립하여 하나의 샤드에 적절한 용량이 할당, 적절한 용량으로 병합되는 것이 중요
: 세그먼트를 병합했을 때, 이후에 색인이 발생되면 다시 세그먼트가 늘어나 무용지물

11.5 그 외의 검색 성능을 확보하는 방법들

: ElasticSearch에서는 문서를 모델링할 때, 간결하게 구성하는 것을 권고, Parent/Child 구조의 join 구성이나 nested 타입같이 문서를 처리할 때, 관계 처리 구성은 권장 x
: painless script를 사용하여 하나의 문서를 처리할 때마다 부가적으로 리소스를 사용하지 않도록 하는 것도 권고 사항
: 레플리카 샤드를 가능한 충분히 둘 것을 권고, 데이터 안정성을 확보하는 역할을 할 뿐만 아니라 검색 요청에 대한 많은 샤드들이 결과를 리턴해 주는 역할

11.6 마치며

1.
ElasticSearch는 다양한 캐시 영역을 두어 사용자의 검색 요청에 대한 내용들을 캐싱하는데, 이 캐시 영역들을 적절히 사용하면 검색 성능을 향상시킬 수 있다.
2.
Node Query Cache는 쿼리 결과를 각 노드에 캐싱하는 영역, 활성화 상태가 기본
3.
Shard Request Cache는 쿼리 결과 중 집계 데이터에 관한 결과를 각 샤드에 캐싱하는 영역, 활성화 상태가 기본
4.
Field Data Cache는 쿼리의 대상이 되는 필드의 데이터들을 캐싱하는 영역, 활성화 상태가 기본
5.
문서를 검색할 대상 필드를 줄이거나, 쿼리의 종류를 바꾸는 것만으로도 검색 성능을 향상시킬 수 있다.
6.
forcemerge API를 활용하여 색인이 끝난 인덱스의 샤드 내 세그먼트를 강제로 병합하면 검색 성능을 향상시킬 수 있다.
7.
꼭 필요한 상황이 아니면 nested 타입과 같은 복잡한 형태의 데이터 타입을 사용하지 말아야 한다.
8.
클러스터 용량에 여유가 있다면 레플리카 샤드를 추가로 만들어서 검색 성능의 향상을 기대할 수 있다.