'split'에 해당되는 글 2건

  1. 2018.04.06 [Elasticsearch] Split Index 기능 맛보기
  2. 2014.02.13 [Java] String split 성능테스트.

[Elasticsearch] Split Index 기능 맛보기

Elastic/ElasticsearchReferences 2018.04.06 14:24

Split index 기능에 대해서 공식 문서에 나와 있는 내용을 그대로 테스트 해봤습니다.

(Shrink 와 Split 은 모두 Resize Action 에 해당 합니다.)


Reference)

https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-split-index.html


이 split index API 는 기존에 존재하는 또는 생성된 index 의 primary shard 를 신규 index 로 기존 primary shard 크기 보다 크게 split 해서 생성해 주는 역할을 합니다.


RESTful endpoint 는 _split 입니다.


근데 7.0 에서는 삭제 된다고 하니 제가 이걸 왜 쓰고 있는지 모르겠습니다.

하지만 늘 그렇듯이 Elasticsearch 에서는 기능이 없어지게 되면 대체 가능한 기능을 추가로 제공해 줍니다. :)


이 API 사용시 제일 중요한 부분은 IMPORTANT 에 잘 나와 있습니다.


The _split API requires the source index to be created with a specific number_of_routing_shards in order to be split in the future. This requirement has been removed in Elasticsearch 7.0.


※ Source index 를 생성 할때 설정을 해줘야 한다는 이야기 입니다.


그럼 문서에 나와 있는 데로 한번 돌려 보겠습니다.

하지 전에, elasticsearch 하나 띄워 놓으시고 kibana 도 띄워 놓으세요. 그래야 편하게 dev tool 이용해서 request 할 수 있겠죠.


Step 1) Preparing an index for splitting

Source index 를 생성 하는 과정이며 이 과정에서 반드시 routing shard 정보를 설정 하셔야 합니다.


PUT my_source_index

{

    "settings": {

        "index.number_of_shards" : 1,

        "index.number_of_replicas" : 0,

        "index.number_of_routing_shards" : 2

    }

}


Step 2) Set read-only mode

Split 하기 전에 반드시 읽기 전용으로 반드시 설정을 하셔야 합니다. 안하시면 에러 납니다.

그럼 왜 해야 할까요?

보통 DB 마이그레이션 작업 하실때 생각을 해보시면 됩니다. :)


PUT /my_source_index/_settings

{

  "settings": {

    "index.blocks.write": true 

  }

}


문서를 자세히 보기 전까지 저 설정이 block 단위로 write 할 수 있도록 해주는 설정인 줄 알았습니다. ^^;


Step 3) Splitting an idex

이제 primary shard 를 2 개로 늘려 보겠습니다.


POST my_source_index/_split/my_target_index

{

  "settings": {

    "index.number_of_shards": 2,

    "index.number_of_replicas" : 0

  }

}


이 단계 작업을 하면서 주의 할 점은 당연한 내용이지만, 

1. target index 가 없어야 겠죠.

2. source index 의 primary shard 보다 커야 겠죠.

3. factor 조건을 만족 해야 합니다.


routingNumShards % numTargetShards != 0 이면 안되구요.


if (sourceNumberOfShards < targetNumberOfShards) { // split

factor = targetNumberOfShards / sourceNumberOfShards;

if (factor * sourceNumberOfShards != targetNumberOfShards || factor <= 1) { 이면 안되구요. }

}


즉,

- 나눠서 나머지가 없어야 합니다.

- target shard 는 routing shard 보다 작거나 같아야 합니다.


아래는 factor 조건을 만족하지 않는 예시 입니다.


PUT my_source_index

{

    "settings": {

        "index.number_of_shards" : 1,

        "index.number_of_replicas" : 0,

        "index.number_of_routing_shards" : 4

    }

}


PUT /my_source_index/_settings

{

  "settings": {

    "index.blocks.write": true 

  }

}


POST my_source_index/_split/my_target_index

{

  "settings": {

    "index.number_of_shards": 3,

    "index.number_of_replicas" : 0

  }

}


조건 1) 

4 % 3 => 1 // 0 이 되어야 합니다.


조건 2) 

assert getRoutingFactor(3, 4) >= 0


if ( 3 < 4 ) {

    factor = 4 / 3; // factor = 1

    if ( factor * 3 != 4 || factor <= 1) {

        throw new IllegalArgumentException(.....);

    }

}



혹시라도 사용하셔야 하는 분들이 계시다면 참고 하시면 되겠습니다.

Trackback 0 : Comment 0

[Java] String split 성능테스트.

ITWeb/개발일반 2014.02.13 16:30

아래 코드에 오류가 있습니다.

뭐 수정은 안할 예정이구요. ㅋㅋ 알아서 하세요.

딱 보면 논리적으로 틀린 부분이 보입니다.

힌트, 첨 부터 구분할 대상이 없다면.........ㅋ

=============================================================================


뭐 성능 테스트라고 하기까지는 그렇고 String.split 이 성능이 나쁘다는 사실은 잘 알고 있을 거라고 생각 합니다.

그래서 가능 하면 이넘을 안쓰려고 하는데요.

기본적으로 비교 되는 것들이 scanner vs split vs tokenizer 인데요.

이건 이미 비교 자료가 많으니 일단 pass ~


오늘 제가 그냥 테스트한건 split vs indexOf 형변환 vs indexOf 입니다.

편의상 이름을 아래 처럼 하겠습니다.

String.split vs split vs tokenizer


[테스트 코드]


    @Test
    public void testSplit() {
        String original = "field1,field2,field3,field4,field5,field6,field7,field8,field9,field10";
        String[] tokens;
        List tokenList;
       
        long startTime = 0;
        int elapsedTime = 0;
        long loop = 10000000;
       
        startTime = System.currentTimeMillis();
        for ( int i=0; i<loop; i++ ) {
            tokens = original.split(",");
        }
        elapsedTime = (int)(System.currentTimeMillis() - startTime);
        log.debug("String.split EXECUTE:"+elapsedTime);
       
        startTime = System.currentTimeMillis();
        for ( int i=0; i<loop; i++ ) {
            tokens = split(original, ",");
        }
        elapsedTime = (int)(System.currentTimeMillis() - startTime);
        log.debug("split EXECUTE:"+elapsedTime);
       
        startTime = System.currentTimeMillis();
        for ( int i=0; i<loop; i++ ) {
            tokenList = tokenizer(original, ",");
        }
        elapsedTime = (int)(System.currentTimeMillis() - startTime);
        log.debug("tokenizer EXECUTE:"+elapsedTime);
       
    }


[결과]

DEBUG: String.split EXECUTE:7935
DEBUG: split EXECUTE:3253
DEBUG: tokenizer EXECUTE:2896


아래는 테스트로 작성한 split, tokenizer 함수 입니다.

이 함수에 대한 최적화는 pass (그냥 기능만 되는 걸로.. )


    public String[] split(String original, String delimeter) {
        ArrayList<String> tokens = new ArrayList<String>();
        tokens = (ArrayList<String>)tokenizer(original, delimeter);
       
        String[] rets = new String[tokens.size()];
        rets = tokens.toArray(rets);
       
        return rets;
    }
   
    public List tokenizer(String original, String delimeter) {
        ArrayList<String> tokens = new ArrayList<String>();
        String token = "";
        int beginIdx = 0;
        int endIdx = original.indexOf(delimeter);
       
        while ( endIdx > -1 ) {
            token = original.substring(beginIdx, endIdx);
            tokens.add(token);
            beginIdx = endIdx + 1;
            original = original.substring(beginIdx);
            beginIdx = 0;
            endIdx = original.indexOf(delimeter);
           
            if ( endIdx == -1 ) {
                if ( !original.isEmpty() ) {
                    tokens.add(original);
                }
            }
        }
       
        return tokens;
    }


tags : indexof, split, String
Trackback 0 : Comment 0