top bar

글 목록

2015년 8월 3일 월요일

[Elasticsearch] document routing

1. 개요



Elasticsearch는 기본적으로 'shard' 라는 개념으로 구성되어 있다. 이 'shard'라는것은 저장공간을 논리적으로 나눈 단위이다. document가 색인될때, 이 shard에 저장되는데, 이때 내부적인 routing 동작을 통해 각 shard에 분산 저장된다. 즉 유입되는 document들이 각 shard로 퍼지는 것이다.

이런경우, search 동작시에 성능상의 이슈를 불러올 수 있다. 왜냐하면 document를 검색할때에 모든 shard를 다 뒤질 것이기 때문이다. shard의 갯수가 많다면, 그리고 각 shard의 크기가 크다면, 검색은 상당한 시간이 걸릴 것이다.


2. Route



Elasticsearch에서는 이러한 검색 성능 튜닝 방법중의 하나로 'routing'이라는 기능을 제공한다. 이 방식은 routing 기준이 되는 field를 정하고, 그 기준 field의 값에 따라서 하나의 shard로 document를 색인하는 것이다.


3. 예제를 통해 살펴보자



아주 생각하기 쉬운 예를 들어 보겠다. 누구나 학창시절, 학기 초 반배정의 두근두근함을 기억할 것이다. 내가 몇반이 되었을까, 내가 원하는 친구랑 같은 반일까 하는... 기억들 말이다. 뭐 이건 잡설이고..

학생 10명이 있다고 하자, 그중 5명은 'A' 반으로, 3명은 'B' 반으로 그리고 2명은 'C' 반으로 배정을 받았다. 새학기 등교 첫날, 학생들은 각자 배정받은 반의 교실로 입실하여 수업준비를 할 것이다.

이 간단한 예시에서 학생은 'document', 반은 routing 기준이 되는 field, 교실은 'shard'에 비유할 수 있을 것이다.

직접 예제를 수행해 보자.

일단 아래와 같은 bulk 데이터를 준비하자
{"index": {"_index": "school", "_type": "students", "_id": 1}}
{"class": "A", "name": "albert"}
{"index": {"_index": "school", "_type": "students", "_id": 2}}
{"class": "A", "name": "david"}
{"index": {"_index": "school", "_type": "students", "_id": 3}}
{"class": "A", "name": "brown"}
{"index": {"_index": "school", "_type": "students", "_id": 4}}
{"class": "A", "name": "jimmy"}
{"index": {"_index": "school", "_type": "students", "_id": 5}}
{"class": "A", "name": "jennifer"}
{"index": {"_index": "school", "_type": "students", "_id": 6}}
{"class": "B", "name": "hong"}
{"index": {"_index": "school", "_type": "students", "_id": 7}}
{"class": "B", "name": "kim"}
{"index": {"_index": "school", "_type": "students", "_id": 8}}
{"class": "B", "name": "john"}
{"index": {"_index": "school", "_type": "students", "_id": 9}}
{"class": "C", "name": "tomas"}
{"index": {"_index": "school", "_type": "students", "_id": 10}}
{"class": "C", "name": "jamie"}
10명의 학생들에대한 간단한 정보다. 위에 예를 들었던 대로 5명은 A, 3명은 B, 2명은 C 클래스로 배정을 했다.

이제 위의 bulk 데이터를 인덱싱할 인덱스를 만들어야 하겠다. 아래와 같이 인덱스를 생성하자.
$ curl -XPUT 'localhost:9200/school?pretty' -d '{
    "mappings": {
        "students": {
            "_routing": {
                "required": true,
                "path": "class"
            },
            "properties": {
                "class": {
                    "type": "string",
                    "index": "not_analyzed"
                },
                "name": {
                    "type": "string"
                }
            }
        }
    }
}'
주목해야 할 것은 바로 '_routing' 설정이다. required 와 path 두가지 설정을 가지는데, 여기서 'path' 설정에 들어가는 값이 routing 기준이 되는 field 인 것이다.

그 밑에 'properties' 로 각 필드에 대한 설정을 하는데, 여기서 중요한 것은 'path' 설정에 들어간 field의 store 속성은 반드시 'true'로 해야하고 index 속성은 'not_analyzed'로 해야 한다는 것이다. 위의 예시에서 store는 기본값이 true이므로 생략하였고, index 속성은 'not_analyzed'로 설정하였다.

이제 아래의 curl을 이용하여 bulk 데이터를 색인해 보자.
curl -XPUT 'localhost:9200/_bulk?pretty' --data-binary @data.json
참고로 @파일이름 와 같은 형식으로 bulk 데이터 파일을 지정한다. data.json파일은 위의 10명의 학생 정보에 대한 bulk 데이터 파일이다.

일단 아래와 같이 school indice에 10개의 shard가 있다고 가정하자.













기준값 (class) 별로 routing이 잘 되었을까? shard를 하나씩 클릭해봄으로 확인 할 수 있다.














각각 0번, 8번, 9번 shard에 2개, 5개, 3개의 document가 색인 된 것을 볼 수 있다.

조회는 아래와같이 _search api 사용시 query string으로 routing 파라메터를 주어 조회 할 수 있다.
$ curl -XGET 'localhost:9200/school/students/_search?pretty&routing=B'
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "school",
      "_type" : "students",
      "_id" : "6",
      "_score" : 1.0,
      "_source":{"class": "B", "name": "hong"}
    }, {
      "_index" : "school",
      "_type" : "students",
      "_id" : "7",
      "_score" : 1.0,
      "_source":{"class": "B", "name": "kim"}
    }, {
      "_index" : "school",
      "_type" : "students",
      "_id" : "8",
      "_score" : 1.0,
      "_source":{"class": "B", "name": "john"}
    } ]
  }
}
routing파라메터 값을 'B'로 주었고, 그에따라 search api는 모든 shard를 검색하는것이 아니라 class : B 로 routing된 shard만 검색하여 결과를 보내준다.

이러한 routing을 통해서, 특정 데이터를 검색할때 성능을 향상 시킬 수 있는 것이다.

댓글 없음:

댓글 쓰기