Elastic Search

[Elasticsearch] 데이터 모델링 기초

꾸준함. 2024. 6. 6. 01:14

인덱스

  • 인덱스는 도큐먼트를 저장하는 논리적 단위
  • 관계형 데이터베이스의 테이블과 유사한 개념
  • 인덱스에 다수의 도큐먼트가 포함되는 구조인데, 동일한 인덱스에 있는 도큐먼트는 동일한 스키마를 가짐
  • 기본적으로 인덱스는 용량이나 숫자 제한 없이 무한대의 도큐먼트를 포함할 수 있기 때문에 이론적으로는 하나의 인덱스에 수백만, 수억 개의 도큐먼트가 저장될 수 있음
    • 하지만 인덱스 크기가 커질 경우 검색 시 많은 도큐먼트를 참조해야하기 때문에 성능 저하 유발 가능
    • 따라서 운영 환경에서는 인덱스 용량 제한을 두는 것을 권장
    • 기본적으로 특정 도큐먼트 개수에 도달하거나 특정 용량을 넘어서면 인덱스를 분리
    • 혹은 일/주/월/년 단위 같은 날짜/시간 단위로 인덱스를 분리하기도 하며 이 경우 특정 날짜의 데이터를 쉽게 처리 가능

 

인덱스 생성 (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 할 수 있음
  • 인덱스 메타데이터 업데이트 및 자원 해제

 

close
_search API 호출했을 때 400 에러

 

인덱스 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 내부 메타데이터, 문서 일관성 유지에 사용

 

car-master.v3 인덱스 색인 결과

 

2. 문서 색인 UUID

  • _id인 식별자를 지정하지 않고 문서를 업데이트하여 고유한 값인 UUID를 사용하여 각 문서를 구별
    • 앞선 예시는 _id를 명시적으로 1로 부여함

 

  • UUID로 생성되기 때문에 업데이트를 하려면 해당 문서의 ID를 반드시 알아야 함
  • 중복 방지 및 데이터 일관성 유지에 유리

 

kibnana_sample_data_ecommerce

 

단일 문서 조회, 업데이트, 삭제

 

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 값이 변경되었다면, 요청은 실패

 

seq: 0, primary_term: 1

 

seq=0&primary_term=1일 때만 업데이트
업데이트 성공하여 버전 올라가고 seq 올라감

 

쿼리를 활용한 다건 문서 업데이트

 

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
  • 엘라스틱 개발부터 운영까지 (김준영, 정상운 저)
반응형