엘라스틱서치 기본 구조와 매핑
엘라스틱서치의 핵심 개념, 도큐먼트 관리, 매핑과 데이터 타입, 분석기 구성
엘라스틱서치 기본 구조와 매핑
0. Overview
- 클러스터 > 인덱스 > 도큐먼트
관계형 데이터베이스와 엘라스틱서치 비교
RDB Elsaticsearch Table Index Record Document Column Field Schema Mapping
1. Index
- 도큐먼트를 저장하는 논리적 단위
- 인덱스와 도큐먼트는 일대다 관계
- 모든 도큐먼트는 반드시 하나의 인덱스에 포함돼야 한다
- 그룹핑
- 스키마에 따른 그룹핑
- 스키마에 따라 인덱스를 구분하는 것이 기본
- 인덱스 스키마는 매핑을 통해 정의
- 관리 목적의 그룹핑
- 인덱스가 커지면 검색 시 많은 도큐먼트를 참조해야 하기 때문에 성능 저하
- 기본적으로 특정 도큐먼트 개수에 도달하거나 특정 용량을 넘어서면 인덱스를 분리하도록 제한
- 일/주/월/년 단위 같은 날짜/시간 단위로 인덱스를 분리하기도 한다
- 스키마에 따른 그룹핑
2. Document
- 엘라스틱서치에 데이터가 저장되는 기본 단위
- 하나의 도큐먼트는 여러 필드와 값을 가진다
JSON 형식의 도큐먼트 파일
1 2 3 4 5
{ "name": "sypark", "age": 20, "gender": "female" }
2-1. 도큐먼트 생성
- 엘라스틱서치에서 도큐먼트를 인덱스에 포함시키는 것을 인덱싱이라고 한다
- dynamic mapping
- 데이터 타입을 지정하지 않아도 도큐먼트의 필드와 값을 통해 동적 타입 지원
- 묵시적 형변환 지원
- 정수 필드: “10” 입력 -> 10 변환 (« integer 필드에 value를 “10”으로 지정해서 인서트하니까 400에러났는데?)
- 정수 필드: 10.0 입력 -> 10 변환
2-2. 도큐먼트 수정
- 엘라스틱서치 도큐먼트 수정 작업은 비용이 많이 들기 때문에 권장하지 않는다
- 개별 도큐먼트 수정이 많은 작업이라면 다른 데이터베이스를 사용하는 것을 권장
2-3. 도큐먼트 삭제
- 특정 도큐먼트를 삭제하기 위해서는 인덱스명과 도큐먼트 아이디가 필요
- 도큐먼트 삭제 또한 비용이 많이 들어가는 작업이므로 사용에 주의
3. Response Message
엘라스틱서치의 응답 결과로 전달하는 상태 코드 값들은 일반적인 HTTP 프로토콜의 응답 상태 값과 의미가 동일하다
code status 200, 201 정상 수행 4xx 클라이언트 오류 404 인덱스나 도큐먼트가 존재하는지 체크 405 요청 메소드(POST, PUT) 등 API 사용법 다시 확인 429 요청 과부하로 재전송, 노드 추가와 같은 조치 필요 5xx 서버 오류
4. Bulk Data
- bulk API를 통해 API 콜 횟수를 줄여 성능을 향상할 수 있음
- bulk API는 생성/수정/삭제만 지원
- NDJSON(Newline Defined JSON) 포맷으로 작성
- 복수의 JSON 구조를 줄바꿈 문자로 구분
- 각 줄 사이에는 쉼표 등 별도의 구분자가 없고 라인 사이 공백을 허용하지 않는다
- 삭제(delete)만 한 줄로 작성하고 나머지 작업들(index, create, update)은 두 줄로 작성
- 벌크 파일로 요청하기
bulk 파일 생성 후 API 요청
1
curl -H "Content-Type: application/x-ndjson" -XPOST localhost:9200/_bulk --data-binary "@./bulk_index2"
5. Mapping
5-1. dynamic mapping
- 엘라스틱서치의 모든 인덱스는 매핑 정보를 갖고 있지만 유연성을 위해 인덱스 생성 시 매핑 정의를 강제하지 않음
- dynamic mapping 기준
원본 소스 데이터 타입 | dynamic mapping으로 변환된 데이터 타입 |
---|---|
null | 필드를 추가하지 않음 |
boolean | boolean |
float | float |
integer | long |
object | object |
string | string 데이터 형태에 따라 date, text/keyword 필드 |
5-2. 명시적 매핑
- 인덱스의 매핑을 직접 정의
- 인덱스 매핑이 정해지면 새로운 필드를 추가할 수는 있으나, 이미 정의된 필드를 수정하거나 삭제할 수는 없다
- 필드 이름을 변경하거나 데이터 타입을 변경하기 위해서는 새로운 인덱스를 만들거나 reindex API를 사용해야 한다
5-3. 데이터 타입
데이터 형태 | 데이터 타입 | 설명 |
---|---|---|
텍스트 | text | 전문 검색이 필요한 데이터로 텍스트 분석기가 텍스트를 작은 단위로 분리한다 |
keyword | 정렬이나 집계에 사용되는 텍스트 데이터로 분석을 하지 않고 원문을 통째로 인덱싱한다 | |
날짜 | date | 날짜/시간 데이터 |
정수 | byte | signed 8 bit |
short | signed 16 bit | |
integer | signed 32 bit | |
long | signed 64 bit | |
실수 | scaled_float | float 데이터에 특정 값을 곱해서 정수형으로 바꾼 데이터, 정확도는 떨어지나 필요에 따라 집계 등에서 효율적으로 사용 가능 |
half_float | 16 bit 부동소수점 실수 | |
float | 32 bit 부동소수점 실수 | |
double | 64 bit 부동소수점 실수 | |
boolean | boolean | true/false |
IP 주소 | ip | ipv4, ipv6 타입 IP 주소를 입력할 수 있다 |
위치 정보 | geo-point | 위도, 경도 값을 갖는다 |
geo-shape | 하나의 위치 포인트가 아닌 임의의 지형 | |
범위 값 | integer_range, long_range | 정수형 범위 |
float_range, double_range | 실수형 범위 | |
ip_range | IP 주소 범위 | |
date_range | 날짜/시간 데이터 범위 | |
객체형 | object | 계층 구조를 갖는 형태로 필드 안에 다른 필드들이 들어갈 수 있다. name : { “first” : “kim”, “last” : “tony” }로 타입을 정의하면 name.first / name.last로 접근 가능 |
배열형 | nested | 배열형 객체를 저장. 객체를 따로 인덱싱하여 객체가 하나로 합쳐지는 것을 막고, 배열 내부의 객체에 쿼리로 접근 가능 |
join | parent/child 관계를 표현할 수 있다 |
5-4. 멀티 필드를 활용한 문자열 처리
- 텍스트 타입
- 일반적으로 문장이나 여러 단어가 나열된 문자열을 텍스트 타입으로 지정
- 역인덱싱(inverted indexing)
- 텍스트 타입으로 지정된 문자열은 분석기(analyzer)에 의해 토큰(token)으로 분리된다
- 분리된 토큰들은 인덱싱되는데 이를 역인덱싱(inverted indexing)이라 한다
- 역인덱스에 저장된 토큰들을 용어(term)이라고 한다
- 전문 검색이 아닌 집계나 정렬은 키워드 타입을 사용해야 한다
- 텍스트 타입의 경우 기본적으로 집계나 정렬을 지원하지 않으며, 매핑 파라미터로 집계나 정렬을 지원할 수는 있으나 메모리를 많이 사용
- 텍스트 타입으로 지정된 필드를 정렬할 경우 문장의 첫 문자열이 아닌 분해된 용어를 기준으로 정렬 수행
- 전문 검색이 아닌 집계나 정렬은 키워드 타입을 사용해야 한다
- 키워드 타입
- 범주형 데이터에 주로 사용된다
- 키워드 타입은 분석기를 거치지 않고 문자열 전체가 하나의 용어로 인덱싱된다
- 부분 일치 검색은 어렵지만 완전 일치 검색 혹은 집계나 정렬에 사용
- 멀티 필드
- 멀티 필드는 단일 필드 입력에 대해 여러 하위 필드를 정의하는 기능으로 fields라는 매핑 파라미터 사용
- fields는 하나의 필드를 여러 용도로 사용할 수 있게 해준다
멀티 필드 예시
1 2 3 4 5 6 7 8 9 10 11 12 13
{ "mappings" : { "properties" : { "message" : { "type" : "text" }, "contents" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword"} } } } } }
- contents 필드는 텍스트 타입이면서 키워드 타입을 갖는 멀티 타입
- 하위 필드 명으로 keyword 대신 다른 이름을 사용해도 무관하지만 통상적으로 keyword를 많이 사용
- 하위 필드 접근 시에는 .(dot) 사용
- contents.keyword
- 문자열 데이터가 있는데 전문 검색도 해야 하고 집계나 정렬도 필요하다면 멀티 필드가 좋은 수단
7. Index Template
- 인덱스 템플릿은 주로 설정이 동일한 복수의 인덱스를 만들 때 사용
- 관리 편의성, 성능 등을 위해 인덱스를 파티셔닝하는 일이 많은데 이때 파티셔닝되는 인덱스들은 설정이 같아야 한다
- 템플릿을 만들기 전에 이미 존재하던 인덱스는 템플릿 패턴과 일치하더라도 템플릿이 적용되지 않는다
- 템플릿을 지워도 기존 인덱스들은 영향을 받지 않는다
- 새로운 인덱스 템플릿은 우선순위가 높은 템플릿으로 덮어쓰기 된다
- multi_* 패턴(priority: 1) 생성 후 multi_data_(priority: 2) 패턴 생성하면 우선 순위가 높은 multi_data_만 적용
- 다이나믹 템플릿
- 매핑을 정확하게 정할 수 없거나 대략적인 데이터 구조만 알고 있을 때 사용
- 로그 시스템이나 비정형화된 데이터를 인덱싱하는 경우의 경우 필드 타입을 정확히 정의하기 힘들고, 필드 개수를 정할 수 없는 경우도 있음
- 인덱스를 만들 때 dynamic_templates을 추가하면 된다
- 조건에 따라 타입을 매핑할 수 있음
8. Analyzer
- 역인덱싱을 이용한 전문 검색에서 양질의 결과를 얻기 위해 분석기 모듈을 가짐
- 토큰(token)과 용어(term)
- 토큰은 분석기 내부에서 일시적으로 존재하는 상태
- 용어는 인덱싱 된 단위 혹은 검색에 사용되는 단위
8-1. 분석기 구성
분석기 구성요소
구성요소 설명 캐릭터 필터 입력받은 문자열을 변경하거나 불필요한 문자들을 제거한다 토크나이저 문자열을 토큰으로 분리한다. 분리할 때 토큰의 순서나 시작, 끝 위치도 기록한다 토큰 필터 분리된 토큰들의 필터 작업을 한다. 대소문자 구분, 형태소 분석 등의 작업이 가능하다 - 분석기에는 하나의 토크나이저가 반드시 포함되어야 함
- 캐릭터 필터와 토큰 필터는 옵션이므로 없어도 되고 여러 개를 함께 사용해도 된다
- 엘라스틱서치에서 제공하는 분석기를 사용하거나 필터와 토크나이저를 조합한 커스텀 분석기를 사용할 수도 있다
8-2. 토크나이저
- 분석기는 반드시 하나의 토크나이저를 포함해야 한다
8-3. 필터
- 필터는 옵션으로 하나 이상을 포함할 수 있지만, 없어도 분석기를 돌리는 데 문제는 없다
- 필터는 단독으로 사용할 수 없고 반드시 토크나이저가 있어야 한다
This post is licensed under CC BY 4.0 by the author.