'Elastic/Elasticsearch'에 해당되는 글 385건

  1. 2013.11.13 [elasticsearch] unassinged shard reroute...
  2. 2013.10.23 [Elasticsearch] logging.yml appender 추가 하기.
  3. 2013.10.11 [Lucene] score 계산식 알아보기.
  4. 2013.09.24 [Elasticsearch] join 기능 구현은 어떻게?
  5. 2013.09.23 [Elasticsearch] node.local or node.mode .... 2
  6. 2013.09.17 [Elasticsearch] Bulk Indexing 후 Data Consistency 관리.
  7. 2013.09.16 [elasticsearch] Java API : Bulk
  8. 2013.09.16 [Elasticsearch] Sizing 및 설정 일반내용.
  9. 2013.09.11 [Elasticsearch] Indexing performance by kimchy
  10. 2013.09.04 [elasticsearch] filter & facet 사용 시 주의 사항.

[elasticsearch] unassinged shard reroute...

Elastic/Elasticsearch 2013. 11. 13. 15:05

간혹 shard unassigned 되는 경우가 있습니다.

실제 데이터가 깨진게 아니라면 reroute 를 통해서 노드에 할당해 주시면 됩니다.

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-reroute.html

curl -XPOST 'localhost:9200/_cluster/reroute' -d '{
   
"commands" : [ {
       
"move" :
           
{
             
"index" : "test", "shard" : 0,
             
"from_node" : "node1", "to_node" : "node2"
           
}
       
},
       
{
         
"allocate" : {
             
"index" : "test", "shard" : 1, "node" : "node3"
         
}
       
}
   
]
}'


curl -XPOST 'http://localhost:9200/_cluster/reroute' -d '{"commands" : [ {"allocate" : {"index" : "index_test", "shard" : 13, "node" : "genie1", "allow_primary" : true}}]}'


- allow_primary 가 설정 되어 있지 않을 경우 primary shard 는 할당 할 수 없습니다.

:

[Elasticsearch] logging.yml appender 추가 하기.

Elastic/Elasticsearch 2013. 10. 23. 11:08

elasticsearch 에서 logging 관련해서는 log4j 나 slf4j 를 이용하시면 됩니다.

java.util.logging 을 이용할 경우 elasticsearch 가 비정상적으로 동작 하는 문제가 있으니 유의 하시기 바랍니다.


es 패키지 내 Logger, ESLogger 를 사용하셔도 됩니다.

그리고 그냥 일반적으로 log4j 나 slf4j 사용하듯이 사용을 하셔도 됩니다.

아래는 별도 appender 를 하나 추가해서 제가 작성한 플러그인 로그만 따로 뺀 설정 입니다.


[logging.yml]

  logger:

  elasticsearch.analysis: ERROR, failLogger

  additivity:

  elasticsearch.analysis: false

  failLogger:

    type: dailyRollingFile

    file: ${path.logs}/analyzed_fail_docs.log

    datePattern: "'.'yyyy-MM-dd"

    layout:

      type: pattern

      conversionPattern: "%m%n"


별 다른 내용은 없고 형태소 분석이 실패한 문서가 있을 경우 실패한 문서 ID 를 기록해서 다시 색인을 하기 위한 것입니다.


logger 에는 내가 작성한 패키지에 대해서 로그레벨 과 appender 를 지정 하는 것이구요.

additivity 에는 root logger 로 해당 패키지에 대한 로그를 전달 하지 않기 위해 false 로 지정 한 것이구요.

failLogger 는 appender 를 정의 한 것입니다.

:

[Lucene] score 계산식 알아보기.

Elastic/Elasticsearch 2013. 10. 11. 11:25
필요해서 어제 공부 좀 했습니다.

제가 elasticsearch 로 프로젝트를 진행 하고 있습니다.

랭킹과 문서 스코어링 관련해서 문의가 있어서 정확하게 설명을 해줘야 튜닝에 도움이 될 것 같아 글 좀 남겨 봅니다.


검색해 보시면 많은 문서들이 나오는데요.

아래 문서 참고 하시면 좋을 것 같내요.


[참고링크]

http://www.lucenetutorial.com/advanced-topics/scoring.html

http://devyongsik.tistory.com/364 (여긴 울 회사 재화님도 알고 계신 DEV용식님 사이트인데요. 작성 된지 좀 되었지만 이해 하기에는 좋습니다.)

https://lucene.apache.org/core/3_6_2/scoring.html

http://lucene.apache.org/core/4_5_0/core/org/apache/lucene/search/package-summary.html#package_description

http://lucene.apache.org/core/4_5_0/core/org/apache/lucene/search/similarities/TFIDFSimilarity.html  


[참고용 소스코드]

Similarity.java

DefaultSimilarity.java

TFIDFSimilarity.java


lucene 이나 elasticsearch 나 기본은 바로 위에 있는 넘들 가지고 similarity 계산을 하게 됩니다.

소스를 보시면 아시겠지만 아래 요소를 가지고 score 를 계산 합니다.


tf

idf

lengthNorm

queryNorm

coord


소스코드에서 식을 뽑아 보면 이렇습니다.


 TF

 (float)Math.sqrt(freq)

 IDF

 (float)(Math.log(numDocs/(double)(docFreq+1)) + 1.0)^2

 lengthNorm

 state.getBoost() * ((float) (1.0 / Math.sqrt(numTerms)))

 queryNorm

 (float)(1.0 / Math.sqrt(sumOfSquaredWeights))

 coord

 overlap / (float)maxOverlap


이런건 그냥 위에 나온거 보면 다 나오구요.

검색 질의 시 스코어 계산 유형을 살펴 보겠습니다.

(계산 할 때 위에 식에 넣어서 계산 하기 번거로우니 explain 떠서 나온 값들을 사용해서 계산 하도록 하세요.)


1. 검색어 하나 질의

쉽게는 explain 에서 나온 queryWeight * fieldWeight 를 곱하시면 score 가 나옵니다.

score = (queryWeight * fieldWeight)^2


TFIDFSimilarity.html 에 잘 나와 있죠.

score(q,d)   =   coord(q,d)  ·  queryNorm(q)  · ( tf(t in d)  ·  idf(t)2  ·  t.getBoost() ·  norm(t,d) )
t in q
Lucene Practical Scoring Function

이걸 엑셀 같은 데 식을 넣어서 계산 해 보면 값이 나오게 됩니다.

아래 2번에서 풀어 놓은 식을 참고하세요.


2. 검색어 여러개 질의

score = (queryNorm * SUM( tf * idf^2 * fieldBoost * fieldNorm) )^2


3. 필드 부스팅을 포함한 검색어 질의

쉽게는 아래 처럼 풀어서 이해 하시면 됩니다.

score = ((queryWeight * fieldWeight) + (queryWeight * fieldWeight))^2

-> 필드 부스팅 된 필드의 queryWeight 값은 기본 계산이 되어서 나오지만 같은 필드에 같은 term 으로 했을 경우 기본 queryWeight 에 곱하기 boostScore 만큼 해준다고 보면 됩니다.


여기서 필드 부스팅을 한개가 아닌 여러개를 했다면 (queryWeight * fieldWeight) 이넘을 여러번 계산 해서 더하시면 됩니다.


근데 여기서 궁금한거 하나.... 

- fieldNorm 과 sumOfSquaredWeights 는 어떻게 구하나요???

소스 코드를 보시면 됩니다.


[fieldNorm]

computeNorm(), encodeNormValue(), decodeNormValue(), NORM_TABLE 을 참고하세요.

풀면 결국 아래와 같이 됩니다.


fieldNorm = NORM_TABLE[(floatToByte315(1/SQRT(fieldTotalTermsNum)) & 0xFF)];


[sumOfSquaredWeights]

말 처럼 이건 각각의 term 에 대해서 더하셔야 합니다.

1번에서 처럼  sigma 가 붙어 있는 걸 잊으시면 안됩니다.

이해를 돕고자 풀면 아래와 같이 됩니다.

queryBoost^2 * SUM( (idf * fieldBoost)^2 )


가볍게 이해 하는 수준으로만 사용하시고 깊이 있게 이해를 하고 싶으신 분들은 소스 코드를 꼭 드려야 보세요. :)


:

[Elasticsearch] join 기능 구현은 어떻게?

Elastic/Elasticsearch 2013. 9. 24. 12:50

아래 링크 참고해서 설계 및 구현 하시면 되겠습니다.

http://www.elasticsearch.org/blog/managing-relations-inside-elasticsearch/

https://github.com/imotov/elasticsearch-native-script-example

:

[Elasticsearch] node.local or node.mode ....

Elastic/Elasticsearch 2013. 9. 23. 14:52

0.90.5 에 추가 된 node.mode 관련 내용입니다.

기존에는 node.local 설정을 이용했었는데요.

이 설정이 없어진건 아니고 그대로 유지 되면서 이 옵션이 추가 된 것입니다.

node.local: true or false 로 설정을 했었는데요.

node.mode: local or network 으로 설정을 하게 됩니다.


kimchy 말에 의하면 

You set the node to local(true), this means it will not discover other nodes using network, only within the same JVM.

이와 같습니다.


관련 코드는 DiscoveryNode.java, DiscoveryModule.java, TransportModule.java 이 세 파일을 참고 하시면 됩니다.


의미는 노드간 communication 을 할 것인지 말것인지를 설정 하는 것으로 보시면 됩니다.

:

[Elasticsearch] Bulk Indexing 후 Data Consistency 관리.

Elastic/Elasticsearch 2013. 9. 17. 12:35

벌크 인덱싱 후 간혹 샤드간에 데이터가 왔다 갔다 할 때가 있습니다.

이건 elasticsearch 색인이 잘못 되었다고 보시면 안됩니다.

인덱스와 샤드의 status 정보를 보면

- num_docs

- max_docs

- deleted_docs

이런게 있죠.


기본적으로 벌크 색인 시 empty index 에 색인을 하게 될 텐데요.

색인 도중 문제가 발생해서 일부 색인 데이터가 들어가고 다시 같은 인덱스에 색인을 하게 되면  updateDocument 를 실행 하게 됩니다.

뭐 루씬 API 보시면 이제 add/update 가 하나의 API 로 동작 하긴 합니다.

암튼 이렇게 되다 보니 deleted_docs 가 발생 하게 되고 num_docs 와 max_docs 수치가 안맞게 됩니다.

즉, num_docs = max_docs - deleteed_docs 와 같습니다.


이런 관계로 색인 완료 시 recovery 또는 optimize 작업을 통해서 data consistency 를 보정해 주어야 합니다.

그럼 이걸 어떻게 할까요?


아래 명령어로 해보시고  ES  API 문서 참고 하시면 되겠습니다.

(거의 대부분 default value 입니다.)


[Java API]

new OptimizeRequest()

    .indices(indice)

    .flush(true)

    .onlyExpungeDeletes(false)

    .refresh(true)

    .waitForMerge(true)

    .operationThreading(BroadcastOperationThreading.THREAD_PER_SHARD)

    .maxNumSegments(1)



[Rest API]

curl -XPOST 'http://localhost:9200/indice/_optimize?only_expunge_deletes=false&max_num_segments=1&refresh=true&flush=true&wait_for_merge=true'



[Recovery]

curl -XPOST 'http://localhost:9200/indice/_close'

curl -XPOST 'http://localhost:9200/indice/_open'


client.admin()

    .indices()

    .close(new CloseIndexRequest("indice"));


client.admin()

    .indices()

    .close(new OpenIndexRequest("indice"));



[Reference]

http://www.elasticsearch.org/guide/reference/api/admin-indices-optimize/

http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close/


:

[elasticsearch] Java API : Bulk

Elastic/Elasticsearch 2013. 9. 16. 18:34

본 문서는 개인적인 테스트와 elasticsearch.org 그리고 community 등을 참고해서 작성된 것이며,

정보 교환이 목적입니다.


잘못된 부분에 대해서는 지적 부탁 드립니다.

(예시 코드는 성능 및 보안 검증이 되지 않았습니다.)


벌크 색인 시 actionGet(TIMEOUT)  부분에 TIMEOUT 은 빼고 돌리시는게 좋습니다.

돌리시다 보면 timeout exception 이 발생 할 때가 있는데 timeout 값을 제거 하고 돌리시면 관련 에러는 없어집니다.


new OptimizeRequest()

.indices(indice)

.flush(true)

.onlyExpungeDeletes(true)

.refresh(true)

.waitForMerge(true)

.operationThreading(BroadcastOperationThreading.THREAD_PER_SHARD)

.maxNumSegments(1))




[elasticsearch java api 리뷰]

원문 링크 : http://www.elasticsearch.org/guide/reference/java-api/bulk/


- 이 API는 한번의 요청으로 여러개의 문서를 색인 또는 삭제 할 수 있습니다.


우선 원문에 나와 있는 예제 부터 살펴 보겠습니다.


[원문예제]

BulkRequestBuilder bulkRequest = client.prepareBulk();


// either use client#prepare, or use Requests# to directly build index/delete requests

bulkRequest.add(client.prepareIndex("twitter", "tweet", "1")

        .setSource(jsonBuilder()

                    .startObject()

                        .field("user", "kimchy")

                        .field("postDate", new Date())

                        .field("message", "trying out Elastic Search")

                    .endObject()

                  )

        );


bulkRequest.add(client.prepareIndex("twitter", "tweet", "2")

        .setSource(jsonBuilder()

                    .startObject()

                        .field("user", "kimchy")

                        .field("postDate", new Date())

                        .field("message", "another post")

                    .endObject()

                  )

        );

        

BulkResponse bulkResponse = bulkRequest.execute().actionGet();

if (bulkResponse.hasFailures()) {

    // process failures by iterating through each bulk response item

}


- 기본 client.prepareIndex() 를 이용해서 문서 하나를 색인 요청 하는 것과 유사 합니다.

- 다만, bulkRequest 의 경우 이런 하나의 문서를 여러개 add(document) 해서 한번에 요청을 한다는 것입니다.

- index name : twitter

- index type : tweet

- document id (_id) : 1 과 2

- document id 를 지정 하지 않을 경우 자동으로 생성을 하게 됩니다.


아래 예제는 글 http://jjeong.tistory.com/792 에서 생성한 index 에 bulkRequest 를 보내는 것입니다.


[간단한 Bulk Request 예제]

BulkRequestBuilder bulkRequest;

BulkResponse bulkResponse;

String ts;

bulkRequest = client.prepareBulk();

int i=0;

for (i=0; i<100000; i++) {

ts = String.valueOf(System.currentTimeMillis());


bulkRequest.add(client.prepareIndex("facebook", "facebook_post")

.setRouting(ts)

.setOperationThreaded(false)

.setSource(jsonBuilder()

.startObject()

.field("docid", ts)

.field("title", "document "+String.valueOf(i))

.endObject()

)

)

.setReplicationType(ReplicationType.ASYNC)

.setConsistencyLevel(WriteConsistencyLevel.QUORUM)

.setRefresh(false);

if ( (i%100) == 0 ) {

bulkRequest.execute().actionGet(5000);

bulkRequest = client.prepareBulk();

log.debug("DOCUMENT Sequence : {}", i);

}

}


bulkRequest.execute().actionGet(5000);

log.debug("DOCUMENT Sequence : {}", i);

- 코드를 보시면 아시겠지만 문서 구조는 docid, title 로 아주 심플합니다.

- docid 에 timestamp를 넣고 document 에는 문자열 "document $SEQ"가 들어 갑니다. 

- 문서를 100개 단위로 묶어서 request 하게 됩니다.


[Bulk Request 고려사항]

- threadpool 세팅을 검토해 보셔야 합니다.

http://www.elasticsearch.org/guide/reference/modules/threadpool/


- refresh 설정을 검토해 보셔야 합니다.

disable 또는 10초 이상 설정


- index merge segment 크기를 조정해야 합니다.

20 또는 30 정도


- threadsafe 하지 않다는 걸 인지해야 합니다.

아직까지는 bulk request 시에 multithread 지원이 되지 않습니다.


- async 방식을 추천 합니다.


:

[Elasticsearch] Sizing 및 설정 일반내용.

Elastic/Elasticsearch 2013. 9. 16. 10:09

Elasticsearch 로 구성하는 일반적인 내용입니다.

서비스 특성과 목적에 맞춰서 구성 하는게 정답이구요.

아래는 ES 의 여러 setting 이나 config 관련된 내용 중 서버 Sizing 과 성능과 관련된 일부 내용입니다. 


[Shard & Replica]

- shard size 조건

shard size 는 replica size 보다 커야 함.

shard 하나당 10G ~100G 정도로 구성.


- replica size 조건

일반 : ceil(N/2) + 1

검색 성능을 높히기 위한 가장 쉬운 방법은 full replica 설정

서비스 특성에 맞춰서 replica 설정을 하는게 좋으며, 일반적으로는 1, 2로 구성함.


[System Recommended]

- 일반적으로는 시스템 사양보다 문서, 검색 그리고 색인 특징을 바탕으로 구성을 하는게 맞습니다.

- 가능 하면 물리서버를 추천 하며, VM 을 사용해도 크게 무리는 없습니다.

- 서비스를 위한 최소사양 ( 아래 사양 보다 낮은 서버로도 구성해서 서비스 하는 것도 있습니다.)

CPU 2.4GHz 쿼드코어

RAM 12G


[검색엔진 설정]

- index settings

refresh_interval

term_index_interval

merge

store

위 설정들은 검색과 색인 특성에 맞춰서 구성을 하시면 됩니다.


- elasticsearch.yml

bootstrap.mlockall

swap 사용을 방지 하기 위해서는 true 로 구성을 하셔야 합니다.

index.fielddata.cache

resident, node, soft 

0.90.3 에서 기본 값은 node 입니다.

성능을 우선시 하는 경우가 아니면 soft 를 사용하시는게 좋구요.

성능을 우선시 하는 경우면 resident 또는 node 를 사용하시는게 좋습니다.

indices.fielddata.cache.size

heap size 의 30 ~40%

indices.cache.filter.size

index.translog

operation 에 대한 transaction log 설정입니다.

type 은 simple, buffer 두 가지 입니다.

안정성을 우선시 할 경우 simple 로 설정 하시는게 좋습니다.

indices.memory.index_buffer_size

전체 메모리 용량에서 20~30% 로 설정 합니다.

threadpool

search, index 별 설정을 해서 사용하시는게 좋습니다.

성능에 관련된 설정입니다.



:

[Elasticsearch] Indexing performance by kimchy

Elastic/Elasticsearch 2013. 9. 11. 17:43

원본 : https://gist.github.com/duydo/2427158



If you want, I can try and help with pointers as to how to improve the indexing speed you get. Its quite easy to really increase it by using some simple guidelines, for example:

- Use create in the index API (assuming you can).
- Relax the real time aspect from 1 second to something a bit higher (index.engine.robin.refresh_interval).
- Increase the indexing buffer size (indices.memory.index_buffer_size), it defaults to the value 10% which is 10% of the heap.
- Increase the number of dirty operations that trigger automatic flush (so the translog won't get really big, even though its FS based) by setting index.translog.flush_threshold (defaults to 5000).
- Increase the memory allocated to elasticsearch node. By default its 1g.
- Start with a lower replica count (even 0), and then once the bulk loading is done, increate it to the value you want it to be using the update_settings API. This will improve things as possibly less shards will be allocated to each machine.
- Increase the number of machines you have so you get less shards allocated per machine.
- Increase the number of shards an index has, so it can make use of more machines.
- Make sure you make full use of the concurrent aspect of elasticsearch. You might not pushing it hard enough. For example, the map reduce job can index things concurrently. Just make sure not to overload elasticsearch.
- Make Lucene use the non compound file format (basically, each segment gets compounded into a single file when using the compound file format). This will increase the number of open files, so make sure you have enough. Set index.merge.policy.use_compound_file to false.

If not using Java, there are more things to play with:

- Try and use the thrift client instead of HTTP.


:

[elasticsearch] filter & facet 사용 시 주의 사항.

Elastic/Elasticsearch 2013. 9. 4. 18:41

주의 사항이라고 할 것 까지는 없지만.. 가끔 당황 스러울때가 있으니 참고 정도 하시면 될 것 같습니다.

elasticsearch 에서

- filter 기능은 검색 질의 후 결과 셋에 대해서 filtering 을 해주는 기능

- facet 의 검색 질의 후 결과에 대한 groupby 연산을 해주는 기능

이라고 보시면 됩니다.


검색 질의 시 filter 기능을 사용하지 않고 구한 facet 결과는 당연히 질의 결과에 대한 facet result 를 줄 것이구요.

filter 기능을 적용하고 동일한 facet 을 적용했을 경우 아래와 같이 처리 됩니다.

- 검색 결과는 filtering 된 값이 나옴

- facet 결과는 초기 검색 식에 의해 나온 결과 셋의 facet result 가 나옴


filter 한 결과와 동일하게 나오게 하고 싶으시다면 filter 조건을 facetFilter 로 적용해 주시면 됩니다.

: