인덱스
- 인덱스는 도큐먼트를 저장하는 논리적 단위
- 관계형 데이터베이스의 테이블과 유사한 개념
- 인덱스에 다수의 도큐먼트가 포함되는 구조인데, 동일한 인덱스에 있는 도큐먼트는 동일한 스키마를 가짐
- 기본적으로 인덱스는 용량이나 숫자 제한 없이 무한대의 도큐먼트를 포함할 수 있기 때문에 이론적으로는 하나의 인덱스에 수백만, 수억 개의 도큐먼트가 저장될 수 있음
- 하지만 인덱스 크기가 커질 경우 검색 시 많은 도큐먼트를 참조해야하기 때문에 성능 저하 유발 가능
- 따라서 운영 환경에서는 인덱스 용량 제한을 두는 것을 권장
- 기본적으로 특정 도큐먼트 개수에 도달하거나 특정 용량을 넘어서면 인덱스를 분리
- 혹은 일/주/월/년 단위 같은 날짜/시간 단위로 인덱스를 분리하기도 하며 이 경우 특정 날짜의 데이터를 쉽게 처리 가능
인덱스 생성 (Settings)
- 인덱스 생성 시 필요한 정보는 기본적으로 생성됨
- 인덱스의 성능 및 데이터 저장 방식을 결정
- 인덱스 생성 후 일부 설정 변경 불가하므로 신중히 설정해야 함
- shard 개수는 생성 후 변경 불가 (number_of_shards)
- replica는 동적으로 변경 가능 (number_of_replicas)
- 만약 불가피하게 설정을 변경해야한다면 _reindex api를 통해 모든 문서를 재색인해야 함
1. 인덱스 생성 시 많이 사용하는 세팅 설정
설정 | 설명 |
number_of_shards | 인덱스를 구성하는 Primary Shard 지정 데이터 분산 및 병렬 처리에 영향을 끼침 |
number_of_replicas | replica shards의 수를 지정 데이터 가용성 및 읽기 처리 증가 |
index.refresh_interval | 인덱스 새로고침 간격 설정 색인된 문서의 검색 가능 시간 설정 |
index.store.type | 인덱스 저장 타입 지정 |
index.codec | 데이터 압축에 사용되는 코덱 설정 |
index.max_result_window | 검색 결과로 반환할 문서의 최대 수 설정 |
2. 인덱스 생성 예시
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PUT sample-index.settings | |
{ | |
"settings": { | |
"index": { | |
"number_of_shards": 1, | |
"number_of_replicas": 2, | |
"refresh_interval": "30s", | |
"store": { | |
"type": "fs" | |
}, | |
"codec": "best_compression" | |
} | |
} | |
} |
인덱스 생성 (Mappings)
- 체계적인 데이터 관리 및 효율적인 검색 지원을 위해 데이터 구조와 저장 및 검색 방식 정의
- 한번 생성된 매핑 정보는 삭제하거나 변경할 수 없지만 인덱스에 필드를 추가적으로 생성하는 것은 가능
- RDBMS로 비교하자면 DML을 통해 테이블에 칼럼 추가
1. 생성된 인덱스 및 매핑 확인하는 방법
- GET [인덱스]/_mapping
- 이미 인덱스가 존재하는 경우 400 에러 발생
- 동적 매핑 사용했을 경우 필드의 매핑이 올바르게 생성되었는지 확인할 때 유용

2. 이미 생성된 인덱스에 매핑 정보를 변경하거나 삭제하는 방법
- 앞서 언급했다시피 이미 생성된 매핑 필드는 삭제 및 변경이 불가능
- 새로운 인덱스를 생성하여 변경된 정보로 매핑 추가
- 기존 인덱스의 모든 문서를 새로운 인덱스로 이관하면서 재색인
- 신규 인덱스에 정상적으로 이관이 되었는지 확인
- 기존 인덱스 삭제
인덱스 생성 과정 및 고려사항
1. 인덱스 생성 과정
- 인덱스 생성 API 호출 시 마스터 노드에 생성
- 마스터 노드는 데이터 노드에 인덱스 생성 요청
- 데이터 노드는 샤드 생성 및 데이터가 색인될 준비
2. 인덱스 생성 시 고려사항
- 인덱스의 샤드 설계 시 리소스가 낭비되지 않도록 주의
- 인덱스 생성 시 한 개의 샤드는 20GB ~ 25GB의 데이터 추가가 적당 (개인적으로는 샤드 당 30GB로 운영하고 있습니다.)
- 샤드의 개수가 많을 수록 색인 시간은 늘어나지만 검색 시간은 줄어듦
- 쓰기와 읽기 횟수를 비교하여 적절히 샤드 개수를 설정
인덱스 삭제
- DELETE [인덱스]
- 인덱스가 존재하지 않는 경우 404 에러 발생
- 샤드, 설정, 매핑, 데이터를 삭제하는 것을 의미
- 사용되지 않는 데이터를 정리하기 위해 인덱스 제거
- 불필요하게 인덱스가 너무 많을 경우 성능 저하 유발
- Elasticsearch ILM 정책에 따라 삭제할 수 없는 로그성 정보일 경우 data_cold, data_frozen 노드로 이관하는 방법도 한 방법
- 일부 누락된 샤드 혹은 오류가 있는 경우 샤드를 제거하기 위해 인덱스 삭제
- 누락된 샤드가 존재할 경우 클러스터 상태가 Yellow 혹은 Red로 변경되기 때문에 문서가 업데이트되지 않을 수 있음
인덱스 삭제 과정 및 고려사항
1. 인덱스 삭제 과정
- 마스터 노드에 인덱스 정보 업데이트
- 클러스터 내 다른 노드와 동기화 필요
- 샤드와 관련된 파일 스토리지에서 제거
- 디스크 공간 확보
2. 인덱스 삭제 시 고려사항
- 인덱스와 관련된 모든 데이터가 디스크에서 제거되기 때문에 주의 필요
- 샤드 누락이나 오류 시 인덱스 삭제로 해결 가능
- 백업 스냅샷이 없을 경우 인덱스 복원 불가
- 데이터 손실 방지를 위한 조치 필요
인덱스 close
- POST [인덱스]/_close
- 인덱스 close 후 조회 시 400 에러 발생
- 인덱스를 사용 불가능한 상태로 만들어 자원 절약하는 방법이며 나중에 다시 open 할 수 있음
- 인덱스 메타데이터 업데이트 및 자원 해제


인덱스 open
- POST [인덱스]/open
- 인덱스를 다시 사용할 수 있는 상태로 만듬
- 클러스터 내 존재하는 인덱스들 중 닫힌 상태의 인덱스만 열 수 있음
- 인덱스를 열었을 때 데이터를 다시 메모리에 올려야 하므로 시스템 부하를 고려해야 함
- 클러스터 상태 및 리소스 사용률 확인 필요
- 트래픽이 적은 시간대에 실행하는 것을 권장
인덱스 재색인 (_reindex)
- 새로운 인덱스에 데이터를 다시 색인해야 하는 경우 사용
- 분석기를 변경하는 경우
- 필드 추가 등의 구조 변경
- 사용하지 않는 필드 제거 등
1. 인덱스 _reindex 파라미터
1-depth | 2-depth | 설명 |
source | index | 복제할 인덱스 혹은 인덱스 목록 |
query | 인덱스 중 일부만 복사하고 싶을 경우 query 필터링 | |
sort | 문서 정렬 방법 정의 | |
dest | _source | 특정 필드만 선택하여 색인 진행 |
index | 복제될 인덱스 | |
pipeline | 수집을 위한 사용자 지정 파이프라인 정의 | |
size | 색인될 문서 수 |
2. 예시
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
POST _reindex | |
{ | |
"source": { | |
"index": "car-master", | |
"query": { | |
"term": { | |
"brand": { | |
"value": "hyundai" | |
} | |
} | |
} | |
}, | |
"dest": { | |
"index": "car-master.v2" | |
} | |
} |
부연 설명
- car-master 인덱스 중 brand가 hyundai인 문서들을 car-master.v2 인덱스에 재색인
인덱스 refresh
- 검색 엔진은 디스크의 사용량을 줄이기 위해 한번에 모아 특정 시간/용량 등의 상태에 따라 문서를 갱신
- Elasticsearch에 설정한 refresh 시간 이후 문서가 정상적으로 업데이트됨
- 너무 빠른 시간에 문서를 갱신하면 시스템의 리소스를 많이 사용하게 되므로 주의 필요
- 기본 색인은 1초마다 인덱스 자동 새로고침이 되며 settings의 index.refresh_interval의 수치를 변경하면 갱신 주기를 조절할 수 있음
- -1일 경우 강제로 업데이트하지 않는 이상 갱신 안됨
- POST [인덱스]/_refresh API 호출을 통해 강제 갱신 가능
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PUT sample-index | |
{ | |
"settings": { | |
"index": { | |
"refresh_interval": -1 | |
} | |
} | |
} |
문서 색인
- 검색 엔진에 문서를 색인하기 위해 JSON 형식으로 저장하며 JSON 객체는 key-value의 형태로 작성
- 문서는 정의된 인덱스명, 필드명, 데이터 타입으로 색인되며 검색 가능한 형태로 변환됨
- PUT [인덱스]/_doc/[문서 번호] API 호출을 통해 색인 가능
1. 문서 색인 결과 주요 항목
항목 | 설명 |
_index | 색인된 문서가 속한 Elasticsearch 인덱스명 데이터 분류 및 구별에 사용 |
_id | 문서의 고유 식별자 문서 조회 및 관리에 용이 |
_version | 문서의 버전 번호 업데이트할 때마다 증가하여 변경 이력 추적 |
result | 문서의 상태, 작업 결과 표시 여기서 문서의 상태란 생성, 업데이트, 삭제 등 |
_shards | 색인 작업이 수행된 샤드의 성공/실패 여부 |
_seq_no & _primary_term | Elasticsearch 내부 메타데이터, 문서 일관성 유지에 사용 |

2. 문서 색인 UUID
- _id인 식별자를 지정하지 않고 문서를 업데이트하여 고유한 값인 UUID를 사용하여 각 문서를 구별
- 앞선 예시는 _id를 명시적으로 1로 부여함
- UUID로 생성되기 때문에 업데이트를 하려면 해당 문서의 ID를 반드시 알아야 함
- 중복 방지 및 데이터 일관성 유지에 유리

단일 문서 조회, 업데이트, 삭제
1. 단일 문서 조회
- GET [인덱스]/_doc/[식별자]
- ex) GET kibana_sample_data_ecommerce/_doc/Qdo-zo8BaVG7uWJU8fmN
- 특정 문서에 빠르게 접근하여 색인한 문서의 내용을 _id 값을 통해 조회
2. 문서 전체 업데이트
- PUT [인덱스]/_doc/[식별자]
- 이미 존재하는 문서 전체 업데이트 (내용 바꿔치기)
- _id를 지정하여 문서를 업데이트하며 문서를 생성하는 방법과 동일
3. 문서의 특정 필드 업데이트
- POST [인덱스]/_update/[식별자]
- _update API를 통해 특정 문서의 데이터 변경 및 추가

부연 설명
- car-master.v3 인덱스 내 첫 번째 문서의 doc.brand를 "닷지"로 변경
4. 스크립트를 통해 문서의 특정 필드 업데이트
- 문서는 색인되면 세그먼트에 저장되고 설계상 한번 생성된 세그먼트는 변경할 수 없음
- 문서 업데이트가 처리되는 방식은 비용이 많이 드는 작업
- 업데이트를 수행하기 위해서는 기존 문서를 삭제하고 업데이트된 문서를 재색인해야 함
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
POST car-master.v3/_update/1 | |
{ | |
"script": { | |
"source": "if (ctx._source.brand == params.brand) {ctx._source.brand = params.replace_brand}", | |
"params": { | |
"brand": "닷지", | |
"replace_brand": "현대" | |
} | |
} | |
} |
부연 설명
- 3번의 예시를 painless script를 통해 재현
5. 문서 삭제
- DELETE [인덱스]/_doc/[식별자]
- 특정 문서를 인덱스에서 제거하며 문서의 고유 ID 사용
- 삭제된 데이터가 결과에 반영되지 않도록 관리
- 효율적인 데이터 관리 및 저장 공간 절약
문서 버전 관리
- Elasticsearch의 버저닝은 데이터의 일관성과 정확성 유지 목적
- 다수의 클라이언트가 동시에 데이터 접근 및 수정 시 충돌할 수 있으므로 이를 방지하기 위해 버저닝 적용
- 문서의 버전을 통한 변경 이력 관리

1. 문서 버전 관리 프로세스
- 문서 검색 및 최신 상태 확인
- 문서의 변경 사항 업데이트 및 새로운 번호 부여
- 다른 사용자가 동일한 문서에 접근하여 업데이트 시도 시 충돌 감지
- 최신 버전 알림 및 재조정 진행
2. 문서 버전 업데이트 시 에러가 발생하는 케이스
- 문서가 업데이트되고 있는 상황에서 현재/이전 버전으로 업데이트 시 에러 발생

3. 문서 버전 업데이트 충돌 방지 방법
- 문서를 업데이트할 때 데이터 일관성을 보장하기 위해 if_seq_no와 if_primary_term을 사용하며 이를 통해 동시에 발생할 수 있는 업데이트 충돌을 방지
- Sequence number는 Elasticsearch에서 각 문서의 업데이트 순서를 추적하기 위해 사용되는 숫자
- 문서가 생성되거나 업데이트될 때마다 해당 숫자 증가
- 해당번호를 통해 Elasticsearch는 문서의 변경 순서를 파악 가능
- Primary term은 해당 문서가 포함된 shard의 primary replica가 변경될 때마다 증가하는 숫자
- 클러스터 리밸런싱, 장애 조치 등으로 primary shard가 다른 노드로 이동하거나 교체될 때 해당 번호 증가
- 이를 통해 클러스터 내의 shard와 관련된 상태 변화를 추적할 가능
- 동시성 제어: if_seq_no와 if_primary_term을 함께 사용하면 특정 조건을 만족할 때만 문서 업데이트가 이루어지도록 할 수 있으며 이를 통해 여러 클라이언트가 동시에 같은 문서를 업데이트하려고 할 때 발생할 수 있는 충돌 방지 가능
3.1 if_seq_no & if_primary_term 사용 예시
- 다음처럼 _seq_no가 0이고 _primary_term이 1인 경우 업데이트 API 요청에 쿼리 파라미터로 if_seq_no=0&if_primary_term=1일 때만 업데이트되도록 동시성 제어
- if_seq_no와 if_primary_term이 일치하는 경우에만 업데이트가 수행되며 만약 다른 클라이언트가 먼저 문서를 업데이트하여 seq_no나 primary_term 값이 변경되었다면, 요청은 실패



쿼리를 활용한 다건 문서 업데이트
1. 문서 업데이트
- _update_by_query API를 사용하여 업데이트
- POST [인덱스]/_update_by_query
- 단일 문서 업데이트가 아닌 여러 문서를 한 번에 업데이트 가능
- 업데이트 쿼리 실행 시 인덱스의 스냅샷을 불러옴
- 내부 버전(internal version)을 사용하여 일치하는 문서 업데이트
- 일치된 문서가 업데이트되면서 version의 번호 증가
- 스냅샷이 생성된 시간과 업데이트 작업 처리 시간 사이에 문서가 변경될 경우 버전 충돌이 발생하고 작업 실패
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
POST car-master.v3/_update_by_query | |
{ | |
"script": { | |
"source": "ctx._source.price = params.price", | |
"params": { | |
"price": "1000" | |
}, | |
"lang": "painless" | |
}, | |
"query": { | |
"term": { | |
"brand.keyword": { | |
"value": "현대" | |
} | |
} | |
} | |
} |
부연 설명
- car-master.v3 인덱스의 문서들을 대상으로 _update_by_query API를 사용하여 일괄 업데이트를 수행
- car-master.v3 인덱스 내에서 brand.keyword 필드가 현대인 모든 문서를 찾아서, 해당 문서들의 price 필드를 1000으로 업데이트
2. 문서 삭제
- POST [인덱스]/_update_by_query
- 일반적인 delete api는 문서의 id 값을 기준으로 삭제되기 때문에 많은 문서를 한 번에 삭제하는 게 어렵지만 _delete_by_query API를 통해 한 번의 호출로 여러 문서 삭제 가능
- document의 _id 값을 부여하지 않고 문서를 색인한 경우 hash 값으로 저장되기 때문에 문서 id로 삭제하는 것이 불가능하지만 _delete_by_query API로는 가능
- 불필요한 데이터 제거로 저장 공간 절약 및 검색 결과 관련성 향상 효과
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
POST car-master.v3/_delete_by_query | |
{ | |
"query": { | |
"term": { | |
"brand.keyword": { | |
"value": "현대" | |
} | |
} | |
} | |
} |
부연 설명
- car-master.v3 인덱스의 문서들을 대상으로 _delete_by_query API를 사용하여 일괄 삭제를 수행
- car-master.v3 인덱스 내에서 brand.keyword 필드가 현대인 모든 문서를 찾아서 제거
Bulk 색인
- 한 번의 검색엔진 요청으로 대량의 문서를 추가, 업데이트, 삭제할 수 있음
- 각각의 요청을 단일로 호출하는 것보다 성능적으로 유리
- 문서의 내용과 함께 인덱스명, _id 등과 같은 메타 데이터를 추가적으로 제공해야 함
- bulk api는 create, index, update, delete를 혼합하여 사용할 수 있음
- create 사용 시 문서가 이미 존재하는 경우 색인되지 않고 실패함
- index를 사용하여 문서를 업데이트해야 함
- index로 문서 색인 시 _id를 지정하지 않으면 _id가 자동으로 생성됨
- 각 쿼리는 독립적으로 실행되며 한 작업은 다른 작업에 영향을 끼치지 않음
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
POST _bulk | |
{"index": {"_index": "car-master.v3", "_id": "1"}} | |
{"brand": "현대"} | |
{"index": {"_index": "car-master.v3", "_id": "2"}} | |
{"brand": "기아"} | |
{"delete": {"_index": "car-master.v3", "_id": "2"}} | |
{"update": {"_index": "car-master.v3", "_id": "1"}} | |
{"doc":{"brand": "KIA"}} |
부연 설명
이 쿼리는 다음과 같은 순서로 작업을 수행합니다.
- car-master.v3 인덱스에 ID가 1이고 brand가 현대인 문서를 추가
- car-master.v3 인덱스에 ID가 2이고 brand가 기아인 문서를 추가
- car-master.v3 인덱스에서 ID가 2인 문서를 삭제
- car-master.v3 인덱스에서 ID가 1인 문서를 업데이트하여 brand를 KIA로 변경
1. 현업에서의 활용
- 실무에서는 대량의 데이터 작업을 효율적으로 관리하기 위해 Bulk API 명령어를 JSON 파일로 작성
- 이렇게 작성된 파일을 curl 명령어를 통해 Elasticsearch에 전달하여 색인 작업을 수행
- 이 방법은 다음과 같은 이유로 많이 사용됨
- 관리 용이성: 명령어를 파일로 관리하면 수정, 재사용, 공유가 용이
- 효율성: 파일로 저장된 명령어를 한 번에 실행함으로써 대량 데이터 처리 시의 네트워크 부담을 줄이고, 속도를 향상
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
curl -XPOST "[es 엔드포인트]/_bulk" -k -H 'Content-Type: application/json' --user [아이디]:[비밀번호] --data-binary [파일명].json |
부연 설명
- -H는 curl의 헤더 옵션으로 NDJSON 타입의 컨텐츠를 사용한다는 의미
- -X는 요청 메서드를 기술하는데 여기서는 POST 메서드를 사용
- --data-binary는 POST 메서드에 파일을 바이너리 형태로 전송해주는 파라미터
- bulk API의 포맷을 무시하고 JSON 형태로 파일을 만들면 bulk API 포맷에 맞지 않는다는 오류가 발생하므로 반드시 NDJSON 형식으로 생성해야 함
참고
- 패스트 캠퍼스 - 고성능 검색 엔진 구축으로 한 번에 끝내는 Elasticsearch
- 엘라스틱 개발부터 운영까지 (김준영, 정상운 저)
반응형
'Elastic Search' 카테고리의 다른 글
[Elasticsearch] 분석기(analyzer) (3) | 2024.06.07 |
---|---|
[Elasticsearch] 매핑과 인덱스 alias, template (1) | 2024.06.06 |
[Elasticsearch] 개념과 용어 정리 (1) | 2024.06.02 |
[Elasticsearch] 설정 관련 정리 (0) | 2022.11.16 |
[Elasticsearch] Components 정리 (5) | 2022.10.12 |