목차
1. 인덱스 설정
인덱스 설정
GET [인덱스 이름]/_settings
Bash
복사
•
number_of_shard
◦
인덱스가 데이터를 몇 개의 샤드로 분리할 지 지정
◦
reindex를 하지 않는한 바꿀 수 없다.
•
number_of_replicar
◦
샤드 하나당 복제본 샤드의 갯수 지정
◦
변경이 가능하다.
PUT [인덱스 이름]/_settings
{
[변경 사항]
}
Bash
복사
PUT my_index/_settings
{
"index.number_of_replicas":0
}
Bash
복사
refresh_interval
•
ES refresh 수행 주기
•
-1로 지정하면 주기적으로 수행하지 않는다.
•
null로 업데이트해서 설정 전으로 되돌릴 수 있다.
PUT my_index/_settings
{
"index.refresh_interval": "1s" # 1초마다 refresh를 하겠다는 의미
}
Bash
복사
index.search.idle.after
•
마지막 쿼리 수행 이후 해당 설정 시간이 지나면 새로운 쿼리 요청이 오기전까지 refresh를 수행하지 않는다.
인덱스 생성
•
설정값 없이 인덱스를 생성하면 모두 기본값으로 지정되는데, 프로덕션 환경에선 적절하지 않다.
PUT [인덱스 이름]
{
"settings": {
[인덱스 설정]
}
}
Bash
복사
PUT my_index2
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 2
}
}
Bash
복사
•
number_of_shard와 replicas 정보가 의도한대로 2로 설정되어 있다.
GET my_index2 결과
매핑과 필드 타입
매핑
•
바로 위 GET my_index2 의 결과 중 mappings라는 key가 보인다.
•
매핑(mapping)은 문서가 인덱스에 어떻게 색인되고 저장되는지를 정의하는 부분이다.
•
JSON 문서의 각 필드를 어떤 방식으로 분석하고 색인할지, 어떤 타입으로 저장할지 지정한다.
•
다음 샘플 데이터를 입력 후 mappings를 확인해보자.
PUT my_index2/_doc/1
{
"title":"hello world",
"views": 1234,
"public": true,
"point":4.5,
"created": "2019-01-17T14:05:01:234Z"
}
GET my_index2
Bash
복사
: 각 필드에 타입과 관련된 정보가 생성되었다.
ES는 새로운 필드가 들어오면 자동으로 문서의 내용을 보고 타입 추론 후 매핑 정보를 생성한다.
이렇게 ES가 자동으로 생성해주는 매핑을 동적 매핑(dynamic mapping) 이라 부른다.
당연히, 반대로 사용자가 직접 지정하는 방법을 명시적 매핑(explicit mapping)이라 부른다.
"mappings": {
"properties": {
"created": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"point": {
"type": "float"
},
"public": {
"type": "boolean"
},
"title": {
"type": "text",
"fields": {
"keyword": {
//멀티 매핑
"type": "keyword",
"ignore_above": 256
}
}
},
"views": {
"type": "long"
}
}
}
Bash
복사
운영 환경에서는 명시적 매핑을 사용하자.
•
대부분의 설정은 한 번 지정되면 사실상 변경이 불가능하다.
•
운영 환경에서 대용량 데이터 처리시에는 기본적으로 명시적 매핑을 사용하자.
PUT mapping_test
{
"mappings": {
"properties": {
"createdDate": {
"type": "date",
"format": "strict_date_time || epoch_millis"
},
"keywordString" :{
"type": "keyword"
},
"textString":{
"type": "text"
}
}
},
"settings": {
"number_of_replicas": 1,
"number_of_shards": 1
}
}
# 매핑정보 추가하기
PUT mapping_test/_mapping
{
"properties":{
"longValue": {
"type":"long"
}
}
}
Bash
복사
필드 타입
•
심플 타입
◦
직관적인 데이터 자료형
◦
숫자형(long, integer, short, float, ..)
◦
date형
▪
format이라는 옵션으로 데이터 형식을 지정할 수 있다.
▪
Ex: strict_date_time || epoch_second
▪
날짜 비교 검색시 ES에서는 어떤 형식으로 들어오더라도 내부적으로 UTC 시간대로 변환하여 epoch milliseconds 형식의 long 숫자로 색인한다.
◦
배열은 별도의 타입은 없고 대괄호[ ] 를 이용하면 된다.
•
계층 구조를 지원하는 타입
◦
필드 하위에 다른 필드가 들어가는 계층 구조 데이터 타입
◦
object
▪
JSON 문서는 필드로 또 다른 객체를 가질 수 있다.
▪
계층 구조에 대한 매핑 정보는 계층적으로 나타난다.
put object_test/_doc/1
{
"price": 2770.75,
"spec": {
"cores":12,
"memory":128,
"storage":8000
}
}
get object_test
###################
"mappings": {
"properties": {
"price": {
"type": "float"
},
"spec": {
"properties": {
"cores": {
"type": "long"
},
"memory": {
"type": "long"
},
"storage": {
"type": "long"
}
}
}
}
}
Bash
복사
◦
하위의 계층화된 속성정보는 평탄화된 키-값으로 색인한다.
{
"price": 2770.75,
"spec.cores": 12,
"spec.memory": 128,
"spec.storage": 8000
}
Bash
복사
◦
계층화된 구조가 배열타입일 경우에는 다음과 같이 색인된다.
put object_test/_doc/2
{
"spec":[
{
"cores":12,
"memory":128,
"storage":8000
},
{
"cores":6,
"memory":64,
"storage":8000
},
{
"cores":6,
"memory":32,
"storage":4000
}
]
}
# 다음과 같이 평탄화되어 색인된다.
{
"spec.cores": [12, 6, 6]
"spec.memory": [128, 64, 32]
"spec.storage": [8000, 8000, 4000]
}
Bash
복사
◦
nested
▪
object 타입과 비슷하지만 배열 내 각 객체를 독립적으로 취급한다.
▪
다른 필드 복합 조건이 object가 or조건에 가깝다면 nested는 and조건에 가깝다.
타입 | object | nested |
용도 | 일반적인 계층 구조 | 배열 내 각 객체를 독립적으로 취급해야 하는 상황 |
성능 | 상대적으로 가볍다 | 상대적으로 무겁다 |
검색 | 일반적인 쿼리 사용 | 전용 nested 쿼리로 감싸서 사용 |
•
text 타입과 keyword 타입
text 타입과 keyword타입의 역색인 과정
◦
둘 다 문자열 필드 타입이다.
◦
text
▪
애널라이저를 통해 값을 분석 후 토크나이징 한 뒤 역색인이 된다. (term)
▪
전문 검색에 적합하다.
▪
fielddata 캐시를 사용한다.
◦
keyword
▪
노멀라이저를 통해 간단한 전처리 후 전체 키워드를 역색인한다.
▪
일치 검색에 적합하다.
▪
doc_values 캐시를 사용한다.
참고: doc_value와 fielddata
•
doc_values
◦
디스크 기반 자료구조로 파일 시스템 캐시를 통해 정렬,집계,스크립트 작업을 수행할 수 있도록 지원한다.
◦
text, annotion_text를 제외한 대부분의 필드는 doc_values를 지원한다.
◦
정렬등의 작업을 할 일이 없는 필드는 doc_values를 끌 수 있다. (속성을 false로 )
•
fielddata
◦
fielddata는 정렬, 집계, 스크립트 작업 수행 시 역색인 전체를 읽어 힙 메모리에 올리는데, 이는 OOM등의 문제 발생 가능성이 있다. 그렇기에 기본적으로는 비활성화(false) 상태이다.
◦
text는 정렬, 집계, 스크립트 작업이 필요할 경우 fielddata라는 캐시를 이용한다.
◦
어지간해선 활성화시키지 말자
_source
•
문서 색인 시점에 ES에 전달된 원본 JSON 문서를 저장하는 메타데이터 필드
•
_source 필드 자체는 역색인 대상이 아니라 검색 대상이 되진 않는다.
•
비활성화 할 경우 재인덱싱이나 업데이트등을 사용할 수 없으니 활성화 해두자.
•
디스크 공간이 절약해야만 한다면 이 설정을 비활성화 하기보단 인덱스 데이터 압축률을 높히자.
PUT codec_text
{
"settings": {
"index": {
"codec": "best_compression" # default(LZ4), best_compression(DEFLATE)
}
}
}
Bash
복사
index
•
해당 필드의 역색인을 만들 것인지 지정할 수 있다.
•
ES 8.1부터는 설정을 false로 설정해도 doc_value를 통해 검색이 수행될 수 있다.
◦
성능은 떨어지지만 디스크 공간을 절약한다.
•
설계 시점에 검색 대상이 될 가능성이 없거나 어쩌다 한번씩만 검색되는 필드는 index를 false로 하는 것도 고려할 수 있다.
put mapping_test/_mapping
{
"properties": {
"notSearchableText": {
"type":"text",
"index": false
},
"docValuesSearchableText": {
"type": "keyword",
"index": false
}
}
}
put mapping_test/_doc/4
{
"textString": "Hello, World!",
"notSearchableText": "World, Hello!",
"docValuesSearchableText": "hello"
}
get mapping_test/_search
{
"query": {
"match": {
"docValuesSearchableText": "hello"
}
}
}
Bash
복사
•
검색 필드를 notSearchableText로 하면 검색되지 않는 걸 볼 수 있는데 notSearchableText는 text 필드이기 때문에 doc_values를 사용하지 않기 때문이다.
•
docValuesSearchableText은 index가 꺼져있어도 doc_values설정을 통해 검색할 수 있었다.
enabled
•
object 타입 필드에만 적용된다.
•
false로 지정된 필드는 ES에서 파싱수행도 하지 않는다. 즉 _source 외에는 저장되는 곳이 없다.
•
역색인이 되지 않았기 때문에 검색도 불가능하고 정렬이나 집계도 안된다.
•
여러 타입이 혼용되는 배열도 enabled가 false면 유효성 체크를 하지 않아 저장할 수 있다.
•
데이터를 _source에서만 확인만 하면 되는 필드가 있다면 false로 설정하는 것을 고려할 수 있다.
애널라이저와 토크나이저
•
text 타입의 데이터는 애널라이저를 통해 여러 텀(term)으로 쪼개져서 색인된다.
애널라이저
•
애널라이저는
◦
0개 이상의 캐릭터 필터
▪
문자열 변형
◦
1개의 토크나이저
▪
변형된 문자열 분리
◦
0개 이상의 토큰 필터로 구성된다.
▪
분리된 토큰에 추가 변형작업 수행
◦
위 과정들을 마치면 분석 완료된 텀(term)이 완성된다.
◦
_analyze 를 통해 어떻게 분석되는지 확인 가능하다.
post _analyze
{
"analyzer": "standard",
"text": "Hello, HELLO, World!"
}
Bash
복사
애널라이저 - 캐릭터 필터
•
텍스트를 캐릭터의 스트림으로 받아 데이터를 추가,변경,삭제한다.
•
빌트인 캐릭터 필터는 다음과 같이 존재한다.
◦
HTML strip: <b>와 같은 요소 안쪽 데이터를 꺼내고, HTML 엔티티 디코딩도 한다.
◦
mapping: 치환할 대상 문자와 치환문자를 맵 형태로 보관한다.
◦
pattern replace: 정규 표현식을 이용해 문자를 치환한다.
애널라이저 - 토크나이저
•
1개의 토크나이저만 지정할 수 있다.
•
standard
◦
기본적인 토크나이저로 Unicode Text Segmentation 알고리즘을 사용하여 텍스트를 단어 단위로 나눈다.
◦
대부분의 문장 부호가 사라진다.
•
keyword
◦
들어온 텍스트를 쪼개지않고 그대로 내보낸다.
•
ngram
◦
min_gram 값 이상 max_gram 값 이하 단위로 쪼갠다.
◦
min_gram : 2 max_gram: 3 으로 설정하고 hello를 토크나이징할 경우
▪
he, hel, el, ell, ll, llo로 토크나이징 된다.
◦
무의미한 공백 문자도 token_chars 속성으로 토큰에 포함시킬 타입의 문자 지정 가능
▪
Letter : 언어의 글자로 분류되는 문자
▪
Digit : 숫자로 분류되는 문자
▪
whitespace : 띄어쓰기나 줄바꿈
▪
punchuation : !나 “같은 문장 부호
▪
symbol : $나 ⎇같은 기호
▪
custom : custom_token_chars 설정을 통해 따로 지정한 커스텀 문자
◦
우선적으로 token_chars 지정되지 않은 문자를 기준으로 토크나이징을 한 뒤 속성에 따라 단어를 토크나이징 한다.
◦
RDB의 Like 유사검색과 유사하게 검색을 구현하고 싶을 때 활용한다.
◦
min_gram과 max_gram의 값 차이는 index.max_ngram_diff으로 제한을 설정할 수 있다.
•
edge_ngrma
◦
ngram과 유사하지만 토큰의 시작 글자를 단어의 시작글자로 고정시킨다.
◦
Hello, World를 토크나이징 할 경우 Hel, Hell, Wor, Worl으로 토크나이징된다.
애널라이저 - 토큰 필터
•
토크나이저를 통해 만들어진 토큰 스트림을 받아 토큰에 대한 후처리를 한다. (추가,변경,삭제)
•
내장 토큰은 다음과 같이 존재한다.
◦
lowercase / uppercase : 토큰을 대/소문자로 만든다.
◦
stop: 불용어를 지정해 제거할 수 있다. (ex: the, a, an, in등)
◦
synonym: 유의어 사전 파일을 지정해 지정된 유의어를 치환한다.
◦
pattern_replace: 정규식을 사용해 토큰의 내용을 치환한다.
◦
stemmer : 지원되는 몇몇 언어의 어간 추출 수행(not korean)
◦
trim: 토큰 전후 공백 제거
◦
truncate: 지정한 길이로 토큰을 자른다.
내장 애널라이저
•
필터와 토크나이저를 조합해둔 내장 애널라이저가 몇 가지 존재한다.
•
standard(default)
◦
standard 토크나이저 + lowercase 토큰 필터
•
simple
◦
letter가 아닌 문자 단위로 토크나이징 후 lowercase 토큰 필터 적용
•
whitespace
◦
whitespace 토크나이저로 구성
•
stop
◦
standard 애널라이저 + stop 토큰 필터
•
keyword
◦
keyword 토크나이저로 구성되어 있다.
◦
분석을 하지 않고 하나의 큰 토큰을 그대로 반환한다.
•
pattern
◦
pattern 토크나이저 + lowercase 토큰 필터
•
language
◦
여러 언어의 분석 지원( 한국어는 지원하지 않는다.)
•
fingerprint
◦
standard 토크나이저
◦
+ lowercase 토큰필터
◦
+ ASCII folding 토큰필터
◦
+ stop 토큰필터
◦
+ fingerprint 토큰필터
애널라이저를 매핑에 적용
•
전체적인 default analyzer 설정과, 타입별 analyzer 지정이 가능하다.
put analyzer_test
{
"settings": {
"analysis": {
"analyzer": {
"default": {
"type": <애널라이저 타입>
}
}
}
},
"mappings": {
"properties": {
"defaultText": {
"type": "text"
},
"standardText": {
"type": "text",
"analyzer": <애널라이저 타입>
}
}
}
}
Bash
복사
•
커스텀 애널라이저를 직접 매핑할수도 있다.
put analyzer_test2
{
"settings": {
"analysis": {
"char_filter": {
"my_char_filter": {
"type": "mapping",
"mappings": [
"i. => 1.",
"ii. => 2.",
"iii. => 3.",
"iv. => 4."
]
}
},
"analyzer": {
"my_analyzer": {
"char_filter": [ "my_char_filter" ],
"tokenizer": "whitespace",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"properties": {
"myText": {
"type":"text",
"analyzer":"my_analyzer"
}
}
}
}
Bash
복사
참고: 한국어 형태소 분석 애널라이저 플러그인
•
공식적으로 ES에서 한국어 형태소 분석을 지원하진 않지만, nori라는 플러그인을 통해 분석할 수 있다.
•
설치 방법
elasticsearch-plugin install [플러그인 이름]
#elasticsearch-plugin install anaysis-nori
Bash
복사
◦
이후 analyzer 속성의 값을 nori로 지정해서 분석하면 된다.
템플릿
•
인덱스 설정, 매핑, 애널라이저같은 설정들을 템플릿화해서 반복작업을 없앨 수 있다.
인덱스 템플릿
PUT _index_template/my_template
{
"index_patterns": [
"pattern_test_index-*",
"another_pattern-*"
],
"priority": 1,
"template": {
"settings" : {
"number_of_shards": 2,
"number_of_replicas": 2
},
"mappings": {
"properties": {
"myTextField": {
"type": "text"
}
}
}
}
}
Bash
복사
•
index_pattern
◦
해당 템플릿을 지정할 인덱스의 네이밍 패턴을 지정한다. priority를 통해 여러 템플릿 중 우선순위 조정도 가능하다.
컴포넌트 템플릿
•
인덱스 템플릿에서 중복되는 블록을 쪼개어 재사용할 수 있게 만들어둔 템플릿
PUT _component_template/my_shard_settings
{
"template": {
"settings": {
"number_of_shards": 2,
"number_of_replicas": 2
}
}
}
PUT _index_template/my_template2
{
"index_patterns": ["timestamp_index-*"],
"composed_of": ["timestamp_mappings", "my_shard_settings"]
}
Bash
복사
라우팅
•
ES에서 인덱스를 구성하는 샤드 중 몇 번 샤드를 대상으로 작업할지 지정하기 위해 사용하는 값
•
작업 대상 샤드 번호는 지정된 라우팅 값을 해시한 후 주 샤드의 개수로 나머지 연산을 수행한 값이 된다.
•
라우팅 값을 지정하지 않으면 _id 값이 기본값이 된다.
•
검색 시(_search) 라우팅 값을 queryString에 작성하면 해당 샤드를 대상으로 검색한다.
put routing_test
{
"settings": {
"number_of_shards":5,
"number_of_replicas":1
}
}
put routing_test/_doc/1?routing=myid
{
"login_id":"myid",
"comment": "hello world",
"created_at": "2020-09-08T22:14:09.123Z"
}
get routing_test/_search?routing=myid
Bash
복사
routing 값 지정 하지 않은 경우
routing 값을 지정한 경우
•
운영 환경에서 라우팅 값을 지정해주는게 성능부분에서 크게 도움이 된다.
◦
Ex: 게시판에서 사용자별 댓글을 색인하고자 할때 사용자의 아이디로 라우팅 값을 지정하면 사용자별 댓글을 조회할 때 검색 성능을 끌어올릴 수 있다.
라우팅 필수 지정 설정
•
라우팅값을 설정하는 것이 선택적(Optional)이 아닌 필수적(required)으로 정책을 통일하고 싶다면 mappings._routing.required 속성 설정을 통해 라우팅 값 명시를 필수로 설정할 수 있다.
PUT routing_test2
{
"mappings": {
"_routing": {
"required": true
}
}
}
PUT routing_test2/_doc/1
{
"comment": "index without routing"
}
Bash
복사
라우팅 값 없이 저장 결과
정리
◦
ES에서 인덱스는 상세설정이 가능한만큼 설정에 주의가 필요하다.
◦
number_of_shard를 통해 인덱스가 몇 개의 샤드로 분리할 지 지정한다.
◦
number_of_replicas를 통해 샤드의 복제본 수를 지정한다.
◦
refresh_interval속성으로 refresh 주기를 정할 수 있다.
◦
인덱스는 자동보단 수동으로 직접 설계해주자
◦
운영 환경에서는 명시적 매핑(explicit mapping)을 사용해주자.
◦
text 타입은 애널라이저를 통해 여러 term으로 쪼개져서 색인된다.
◦
애널라이저는 캐릭터 필터, 토크나이저, 토큰 필터로 구성되어 있다.
◦
한국어는 nori라는 애널라이저 플러그인을 통해 형태소 분석을 할 수 있다.
◦
애널라이저나 인덱스 설정들을 템플릿화 할 수 있다.
◦
템플릿의 중복되는 블록을 분리해 컴포넌트화 할 수 있다.
◦
라우팅 값을 지정해서 검색할 대상 샤드를 좁힐 수 있다.
◦
required속성을 통해 라우팅 지정 정책을 강제할 수 있다.