인덱스
- 인덱스는 도큐먼트를 저장하는 논리적 단위
- 관계형 데이터베이스의 테이블과 유사한 개념
- 인덱스에 다수의 도큐먼트가 포함되는 구조인데, 동일한 인덱스에 있는 도큐먼트는 동일한 스키마를 가짐
- 기본적으로 인덱스는 용량이나 숫자 제한 없이 무한대의 도큐먼트를 포함할 수 있기 때문에 이론적으로는 하나의 인덱스에 수백만, 수억 개의 도큐먼트가 저장될 수 있음
- 하지만 인덱스 크기가 커질 경우 검색 시 많은 도큐먼트를 참조해야하기 때문에 성능 저하 유발 가능
- 따라서 운영 환경에서는 인덱스 용량 제한을 두는 것을 권장
- 기본적으로 특정 도큐먼트 개수에 도달하거나 특정 용량을 넘어서면 인덱스를 분리
- 혹은 일/주/월/년 단위 같은 날짜/시간 단위로 인덱스를 분리하기도 하며 이 경우 특정 날짜의 데이터를 쉽게 처리 가능
인덱스 생성 (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. 인덱스 생성 예시
인덱스 생성 (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. 예시
부연 설명
- car-master 인덱스 중 brand가 hyundai인 문서들을 car-master.v2 인덱스에 재색인
인덱스 refresh
- 검색 엔진은 디스크의 사용량을 줄이기 위해 한번에 모아 특정 시간/용량 등의 상태에 따라 문서를 갱신
- Elasticsearch에 설정한 refresh 시간 이후 문서가 정상적으로 업데이트됨
- 너무 빠른 시간에 문서를 갱신하면 시스템의 리소스를 많이 사용하게 되므로 주의 필요
- 기본 색인은 1초마다 인덱스 자동 새로고침이 되며 settings의 index.refresh_interval의 수치를 변경하면 갱신 주기를 조절할 수 있음
- -1일 경우 강제로 업데이트하지 않는 이상 갱신 안됨
- POST [인덱스]/_refresh API 호출을 통해 강제 갱신 가능
문서 색인
- 검색 엔진에 문서를 색인하기 위해 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. 스크립트를 통해 문서의 특정 필드 업데이트
- 문서는 색인되면 세그먼트에 저장되고 설계상 한번 생성된 세그먼트는 변경할 수 없음
- 문서 업데이트가 처리되는 방식은 비용이 많이 드는 작업
- 업데이트를 수행하기 위해서는 기존 문서를 삭제하고 업데이트된 문서를 재색인해야 함
부연 설명
- 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의 번호 증가
- 스냅샷이 생성된 시간과 업데이트 작업 처리 시간 사이에 문서가 변경될 경우 버전 충돌이 발생하고 작업 실패
부연 설명
- 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로는 가능
- 불필요한 데이터 제거로 저장 공간 절약 및 검색 결과 관련성 향상 효과
부연 설명
- 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가 자동으로 생성됨
- 각 쿼리는 독립적으로 실행되며 한 작업은 다른 작업에 영향을 끼치지 않음
부연 설명
이 쿼리는 다음과 같은 순서로 작업을 수행합니다.
- 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에 전달하여 색인 작업을 수행
- 이 방법은 다음과 같은 이유로 많이 사용됨
- 관리 용이성: 명령어를 파일로 관리하면 수정, 재사용, 공유가 용이
- 효율성: 파일로 저장된 명령어를 한 번에 실행함으로써 대량 데이터 처리 시의 네트워크 부담을 줄이고, 속도를 향상
부연 설명
- -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 |