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을 통해서, 특정 데이터를 검색할때 성능을 향상 시킬 수 있는 것이다.
댓글 없음:
댓글 쓰기