본문 바로가기

Data Base/NoSQL

Elasticsearch 기본

엘라스틱 서치란

엘라스틱 서치는 NoSQL 기반의 문서 지향 데이터베이스로 RDBMS와 같은 방법론으로 설계하는 것은 옳지 않다. 엘라스틱 서치에서는 기존에 알려진 방식으로 데이터 모델링을 할 수 없다. 엘라스틱 서치의 데이터 모델링은 데이터의 유형, 검색 조건, 집계·시각화 여부 등에 따라 적절한 데이터 모델링 방법을 선택하여 적용해야 한다.

 

  • NoSQL (No Structured Query Language)
  • 분산 처리를 통해 빠른 검색 가능
  • HTTP를 통해 JSON형식의 Restful API 이용
  • RDBMS에서 LIKE 검색할 때와 달리 검색어의 대소문자에 유연
  • 비정형 데이터도 검색 가능
  • 분석 통계 유용
  • 전문 검색(Full-text Search; 내용 전체를 색인해서 특정 단어가 포함된 문서를 검색) 가능
  • 멀티테넌시(Multi-tenancy; 상이한 인덱스일지라도 동일한 필드명을 대상으로 검색 가능)
  • 트랜잭션과 롤백 기능을 제공하지 않으므로 데이터 손실의 위험도 있음
  • 업데이트 명령 시, 기존 내용을 삭제하고 새로 생성하는 방식

 


엘라스틱 서치와 관계형 데이터베이스(RDBMS)의 용어 비교

엘라스틱 서치 관계형 데이터베이스
인덱스 (Index) 데이터베이스 (Database)
샤드 (Shard) 파티션 (Partition)
타입 (Type)
  • 엘라스틱서치 6.1버전부터 하나의 인덱스에는 하나의 타입만 사용 가능
테이블 (Table)
문서 (Document)
  • 데이터가 저장되는 최소 단위
  • JSON 포맷으로 저장됨
  • 하나의 문서는 다수의 필드로 구성
  • 문서 안에 문서도 가능
행 (Row)
필드 (Field) 열 (Column)
매핑 (Mapping) 스키마 (Schema)
Query DSL SQL

 


인덱스(Index) - 설정(Settings)과 매핑(Mappings)

인덱스는 하나의 노드에만 존재하지 않고 샤드 단위로 구분되어 여러 노드에 걸쳐 저장되어 데이터 무결성의 보장과 검색 성능의 향상을 실현한다. 모든 인덱스는 두 개의 정보 단위를 가지고 있는데 바로 settings 과 mappings 이다. 인덱스를 처음 생성한 뒤 GET <인덱스명> 으로 조회하면 설정(settings) 그리고 매핑(mappings) 정보를 확인할 수 있다.

 

설정 (Settings)

number_of_shards 설정은 인덱스를 처음 생성할 때 한번 지정하면 바꿀 수 없다. 샤드 수를 바꾸려면 새로 인덱스를 정의하고 기존 인덱스의 데이터를 재색인 해야 한다. number_of_replicas 설정은 다이나믹하게 변경이 가능하다. 이미 선언된 my_index의 복제본 카피 개수를 1에서 2로 변경하려면 인덱스명 뒤에 _settings API로 접근해서 변경할 설정만 입력해서 변경이 가능하다.

// code placeholder
{
  "settings": {
    "index": {
      "number_of_shards": 3,
      "number_of_replicas": 1
    }
  }
}

analyzer, tokenizer, filter 도 settings 내부에 정의한다. 

 

// code placeholder
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "type": "custom",
          "char_flter": [ "...", "..." ... ]
          "tokenizer": "...",
          "filter": [ "...", "..." ... ]
        }
      },
      "char_filter":{
        "my_char_filter":{
          "type": "…"
          ... 
        }
      }
      "tokenizer": {
        "my_tokenizer":{
          "type": "…"
          ...
        }
      },
      "filter": {
        "my_token_filter": {
          "type": "…"
          ...
        }
      }
    }
  }
}

{{"analysis": { }}} 내부에 {{"analyzer": { }}}, {{"char_filter":{ }}}, {{"tokenizer": { }}}, {{"filter": { }}} 를 입력하고 각자의 내부에서 임의의 이름을 주어 각 기능들을 정의한다. 각 내부에 하나 이상을 생성할 수도 있으며 애널라이저에서는 사용자가 정의한 토크나이저, 토큰 필터를 사용하거나 Elasticsearch 안에 미리 정의되어 있는 것들의 사용이 가능하다. {{"analysis": { }}} 내용은 한번 생성 후 변경은 불가능하다. 이미 만들어진 인덱스에 애널라이저나 토크나이저 등을 추가하거나 사전을 변경하려면 인덱스를 먼저 _close 한 후에 추가하고 다시 _open 해서 적용할 수 있다.

 

 

매핑 (Mappings)

Elasticsearch 를 활용하면서 가장 손이 많이 가는 작업이 매핑 설정이다. 데이터가 입력되어 자동으로 매핑이 생성되기 전에 미리 먼저 인덱스의 매핑을 정의 해 놓으면 정의 해 놓은 매핑에 맞추어 데이터가 입력된다. 매핑은 다음과 같이 선언한다.

// code placeholder
{
  "mapping": {
    "properties": {
      "<필드명>": {
        "type": "<필드 타입>"
        ... <필드 설정>
      }
      ...
    }
  }
}

인덱스의 매핑에서 필드들은 mappings 아래 properties 항목의 아래에 지정된다. 데이터 형식에 맞게 자동으로 데이터 타입이 지정된다. 매핑 파라미터는 아래와 같다.

파라미터 특징
anlayzer
  • 해당 필드의 데이터를 형태소 분석의 대상으로 함
  • 색인 및 검색 시 지정한 분석기로 형태소 분석을 수행 (디폴트 standard analyzer)|
normalizer
  • term query에 분석기를 사용하기 위함
  • asciifolding 필터를 사용하면 cafe, Cafe, Café를 같은 데이터로 인식
boost
  • 필드에 가중치 부여 → 유사도(_score) 산출이 달라짐 → 검색 결과 노출 순서에 영향 
  • 색인 시점에서 사용하면 가중치를 변경할 수 없으므로 검색 시점에서 사용하는 것을 권장
    (루씬7.0부터 색인 시 BOOST 설정 기능이 제거되어 최신 엘라스틱 서치도 불가능해짐)
coerce
  • 색인 시 자동 변환을 허용할지 여부
copy_to
  • 해당 필드의 값을 지정한 필드로 복사 (keyword to text인 경우, 형태소 분석도 가능)
fielddata
  • 엘라스틱서치가 힙 공간에 생성하는 메모리 캐시
  • 형태소 분석을 하는 text 타입의 경우 집계/정렬을 수행하기 위해 사용
  • 메모리 부족 현상 등으로 최소한 사용 권장
  • 디폴트는 false, 활성화 코드는 아래 참고

 

// code placeholder
PUT [인덱스명]/_mapping/_doc
{ 
  "properties" : {
    "[컬럼명]" : {
      "type" : "text", 
      "fielddata" : true
    }
  }
}

 

 

멀티 필드(Multi Field)

Elasticsearch 의 도큐먼트에는 하나의 필드값만 있지만, 이 필드의 값을 여러 개의 역 색인 및 doc_values 들로 저장할 수 있는 다중 필드, 즉 멀티 필드 기능이 있다. 

// code placeholder
{
  "mapping": {
    "properties": {
      "<필드명1>": {
        "type": "text",
        "fields": {
          "<필드명2>": {
            "type": "<타입>"
          }
        }
      }
    }
  }
}