2.X/7. Administration Monitoring Deployment

7-3-3. Indexing Performance Tips

drscg 2017. 9. 23. 12:02

If you are in an indexing-heavy environment, such as indexing infrastructure logs, you may be willing to sacrifice some search performance for faster indexing rates. In these scenarios, searches tend to be relatively rare and performed by people internal to your organization. They are willing to wait several seconds for a search, as opposed to a consumer facing a search that must return in milliseconds.

기반 시설에 대한 로그를 색인 하는 경우처럼, 많은 색인이 있는 환경에서는, 더 빠른 색인를 위해, 몇 가지 검색 성능을 포기할 수도 있을 것이다. 이런 시나리오에서, 검색은 상대적으로 드물고, 조직 내부의 사람에 의해 수행된다. 수 ms 내에 반환해야 하는, 고객을 직접 응대하는 검색과는 대조적으로 그들은 검색 시에 몇 초 정도는 기다려 줄 것이다.

Because of this unique position, certain trade-offs can be made that will increase your indexing performance.

이런 독특한 위치 때문에, 색인 성능을 향상시킬 수 있는 특정 절충점이 있다.

Test Performance Scientificallyedit

Performance testing is always difficult, so try to be as scientific as possible in your approach.Randomly fiddling with knobs and turning on ingestion is not a good way to tune performance. If there are too many causes, it is impossible to determine which one had the best effect. A reasonable approach to testing is as follows:

성능 테스트는 항상 어렵다. 따라서, 접근 방식이 가능한 한 과학적이어야 한다. 무작위로 설정하고 색인을 조정하는 것은 성능을 조정하는 좋은 방법이 아니다. 너무 많은 원인 이 있는 경우에는, 어느 것이 가장 좋은 효과 를 가져오는지를 결정하기가 불가능하다. 테스트에 합리적인 접근은 아래와 같다.

  1. Test performance on a single node, with a single shard and no replicas.

    replica가 없는 하나의 shard를 가지고, 단일 node에서 성능을 테스트하자.

  2. Record performance under 100% default settings so that you have a baseline to measure against.

    측정할 수 있는 기준을 위해, 100% 기본 설정에서 성능을 기록하자.

  3. Make sure performance tests run for a long time (30+ minutes) so you can evaluate long-term performance, not short-term spikes or latencies. Some events (such as segment merging, and GCs) won’t happen right away, so the performance profile can change over time.

    짧은 기간의 급증이나 대기 시간이 아닌, 긴 시간의 성능을 평가할 수 있도록 하기 위해, 성능 테스트는 오랜 시간(최소 30분 이상)동안 실행하자. 어떤 이벤트(예: segment 병합이나 GC 등)는 즉시 일어나지 않을 것이다. 따라서, 성능의 윤곽은 시간에 따라 변할 수 있다.

  4. Begin making single changes to the baseline defaults. Test these rigorously, and if performance improvement is acceptable, keep the setting and move on to the next one.

    기준 기본값에서 하나만 변경해서 시작하자. 이것을 엄격하게 테스트하고, 성능 향상이 나타나면, 그 설정을 유지하고, 다음 단계로 이동하자.

Using and Sizing Bulk Requestsedit

This should be fairly obvious, but use bulk indexing requests for optimal performance. Bulk sizing is dependent on your data, analysis, and cluster configuration, but a good starting point is 5–15 MB per bulk. Note that this is physical size. Document count is not a good metric for bulk size. For example, if you are indexing 1,000 documents per bulk, keep the following in mind:

성능 최적화를 위해, bulk 색인 요청을 사용하는 것이 좋다. bulk의 크기는 데이터, 분석기, cluster 구성에 따라 다르겠지만, 좋은 출발점은 bulk당 5 ~ 15 MB이다. 이것은 물리적 크기임을 기억하자. document의 수는 bulk 크기에 대한 좋은 통계가 아니다. 예를 들어, bulk 당 1,000개의 document를 색인 한다면, 다음을 기억하도록 하자.

  • 1,000 documents at 1 KB each is 1 MB.

    각각 1 KB인 1,000개의 document는 1 MB

  • 1,000 documents at 100 KB each is 100 MB.

    각각 100 KB인 1,000개의 document는 100 MB

Those are drastically different bulk sizes. Bulks need to be loaded into memory at the coordinating node, so it is the physical size of the bulk that is more important than the document count.

저것은 크게 다른 bulk 크기이다. bulk는 조정 node의 메모리에 로드되어야 한다. 따라서, document의 수보다, bulk의 물리적인 크기가 더 중요하다.

Start with a bulk size around 5–15 MB and slowly increase it until you do not see performance gains anymore. Then start increasing the concurrency of your bulk ingestion (multiple threads, and so forth).

5 ~ 15 MB정도의 bulk 크기로 시작해서, 더 이상 성능 향상을 얻을 수 없을 때까지, 천천히 크기를 증가시키자. 그 다음에, bulk 색인의 동시성을 증가(multi thread 등으로)시키자.

Monitor your nodes with Marvel and/or tools such as iostattop, and ps to see when resources start to bottleneck. If you start to receive EsRejectedExecutionException, your cluster can no longer keep up: at least one resource has reached capacity. Either reduce concurrency, provide more of the limited resource (such as switching from spinning disks to SSDs), or add more nodes.

자원이 병목 현상을 나타내기 시작할 때를 알 수 있는, marvel 이나 iostattopps 같은 tool로 node를 모니터하자. EsRejectedExecutionException 이 나타나기 시작하면, cluster는 더 이상 따라 갈 수 없다. 최소한 하나의 자원이 최대 용량에 도달했다는 의미이다. 동시성을 줄일거나 부족한 자원을 더 많이 공급(SSD로 교체)하거나 node를 추가해야 한다.

Note

When ingesting data, make sure bulk requests are round-robined across all your data nodes. Do not send all requests to a single node, since that single node will need to store all the bulks in memory while processing.

데이터를 색인하는 경우에, bulk request가 모든 data node에 순차적으로 접근하는지 반드시 확인하자. 모든 request를 단일 node로 보내지 마라. 왜냐하면, 해당 node는 처리하는 동안 모든 bulk를 메모리에 보관하기 때문이다.

Storageedit

Disks are usually the bottleneck of any modern server. Elasticsearch heavily uses disks, and the more throughput your disks can handle, the more stable your nodes will be. Here are some tips for optimizing disk I/O:

Disk는 일반적으로 현 시대의 모든 서버에서 병목 현상을 보여준다. Elasticsearch는 disk를 아주 많이 사용하고, disk가 처리할 수 있는 양이 많을수록 node는 더 안정적일 것이다. 아래에 disk I/O를 최적화하는 몇 가지 팁이 있다.

  • Use SSDs. As mentioned elsewhere, they are superior to spinning media.

    SSD를 사용하자. 다른 곳에서도 언급했지만, HDD보다 더 우수하다.

  • Use RAID 0. Striped RAID will increase disk I/O, at the obvious expense of potential failure if a drive dies. Don’t use mirrored or parity RAIDS since replicas provide that functionality.

    RAID 0를 사용하자. 드라이브에 문제가 발생하는 잠재적인 상황에 대비하는 대신, striped RAID는 디스크 I/O를 증가시킨다. replica라는 기능을 제공하므로, mirror나 parity RAIDS를 사용하지 마라.

  • Alternatively, use multiple drives and allow Elasticsearch to stripe data across them via multiple path.data directories.

    그 대신에, 다수의 drive를 사용하고, 다수의 path.data 디렉토리를 통해, Elasticsearch가 그들에게 데이터를 분산하여 저장하도록 하자.

  • Do not use remote-mounted storage, such as NFS or SMB/CIFS. The latency introduced here is antithetical to performance.

    NFS나 SMB/CIFS 같은 원격 저장소를 사용하지 말자. 여기에 소개된 대기 시간은 성능과 상반된다.

  • If you are on EC2, beware of EBS. Even the SSD-backed EBS options are often slower than local instance storage.

    EC2를 사용 중이라면, EBS를 조심하자. SSD-backed EBS 옵션은 가끔 로컬 드라이브보다 더 느리다.

Segments and Mergingedit

Segment merging is computationally expensive, and can eat up a lot of disk I/O. Merges are scheduled to operate in the background because they can take a long time to finish, especially large segments. This is normally fine, because the rate of large segment merges is relatively rare.

segment 병합은 계산 비용이 비싸고, 디스크 I/O를 많이 잡아 먹을 수 있다. 병합은 특히 큰 segment에서, 완료하는데 오랜 시간이 소요될 수 있기 때문에, background로 실행되도록 예정되어 있다. 큰 segment 병합의 비율은 상대적으로 드물기 때문에, 이것은 일반적으로 괜찮다.

But sometimes merging falls behind the ingestion rate. If this happens, Elasticsearch will automatically throttle indexing requests to a single thread. This prevents a segment explosionproblem, in which hundreds of segments are generated before they can be merged. Elasticsearch will log INFO-level messages stating now throttling indexing when it detects merging falling behind indexing.

그러나, 때때로 병합이 색인 속도보다 뒤진다. 이런 일이 발생하면, Elasticsearch는 자동으로 색인요청을 하나의 thread로 조절한다. 이것은 segment가 병합되기 전에, 수백 개의 segment가 생성되는 segment의 폭발적 증가(segment explosion) 문제를 방지한다. Elasticsearch는 병합이 색인보다 뒤지는 현상이 감지되면, 지금부터 색인을 조절하기 시작한다(now throttling indexing) 는 INFO 수준의 메시지를 로그에 기록한다.

Elasticsearch defaults here are conservative: you don’t want search performance to be impacted by background merging. But sometimes (especially on SSD, or logging scenarios), the throttle limit is too low.

Elasticsearch는 여기에서 기본적으로 보수적이다. background 병합이 검색 성능에 영향을 끼치는 것을 바라지 않을 것이다. 그러나 때때로, (특히 SSD나 로깅 시나리오에서) 조절 제한이 너무 낮다.

The default is 20 MB/s, which is a good setting for spinning disks. If you have SSDs, you might consider increasing this to 100–200 MB/s. Test to see what works for your system:

기본값은 HDD에서는 좋은 설정인 20mb/s이다. SSD를 가지고 있다면, 이것을 100 ~ 200 MB/s로 증가시키는 것을 고려해야 한다. 시스템에서 어떻게 동작하는지 확인하기 위해 테스트해 보자.

PUT /_cluster/settings
{
    "persistent" : {
        "indices.store.throttle.max_bytes_per_sec" : "100mb"
    }
}

If you are doing a bulk import and don’t care about search at all, you can disable merge throttling entirely. This will allow indexing to run as fast as your disks will allow:

bulk import를 하는 동안, 검색을 전혀 고려하지 않는다면, 병합 조절을 완전히 비활성화할 수 있다. 이렇게 하면, 색인은 디스크가 허용하는 만큼 빠른 속도로 동작한다.

PUT /_cluster/settings
{
    "transient" : {
        "indices.store.throttle.type" : "none" 
    }
}

병합 조절을 완전히 비활성화하기 위하여, throttle type을 none 으로 설정하였다. import가 완료되면, 조절을 다시 활성화하기 위해, 그것을 다시 merge 로 설정한다.

If you are using spinning media instead of SSD, you need to add this to your elasticsearch.yml:

SSD가 아닌 HDD를 사용한다면, elasticsearch.yml 에 다음을 추가할 수 있다.

index.merge.scheduler.max_thread_count: 1

Spinning media has a harder time with concurrent I/O, so we need to decrease the number of threads that can concurrently access the disk per index. This setting will allow max_thread_count + 2threads to operate on the disk at one time, so a setting of 1 will allow three threads.

HDD는 동시 I/O가 더 어렵기 때문에, index 별로 디스크를 동시에 액세스하는 thread의 수를 줄여야 한다. 이 설정은 동시에 디스크에서 동작할 수 있는 thread의 수를 max_thread_count + 2 로 설정한다. 따라서 1 로 설정하면, thread는 3이 된다.

For SSDs, you can ignore this setting. The default is Math.min(3, Runtime.getRuntime().availableProcessors() / 2), which works well for SSD.

SSD의 경우에는, 이 설정을 무시할 수 있다. 기본값은 SSD에서 잘 동작하는 Math.min(3, Runtime.getRuntime().availableProcessors() / 2) 이다.

Finally, you can increase index.translog.flush_threshold_size from the default 512 MB to something larger, such as 1 GB. This allows larger segments to accumulate in the translog before a flush occurs. By letting larger segments build, you flush less often, and the larger segments merge less often. All of this adds up to less disk I/O overhead and better indexing rates. Of course, you will need the corresponding amount of heap memory free to accumulate the extra buffering space, so keep that in mind when adjusting this setting.

마지막으로, 기본값이 512 MB인 index.translog.flush_threshold_size 를, 더 큰, 예를 들어 1 GB로 증가시킬 수 있다. 이것은 flush가 일어나기 전에, 더 큰 segment를 translog에 축적할 수 있도록 한다. 더 큰 segment가 구축되게 하면, flush 간격이 길어지고, 더 큰 segment의 병합 빈도가 줄어든다. 이 모든 것은 더 적은 디스크 I/O의 오버헤드와 더 나은 색인 속도가 된다. 물론, 추가 버퍼링 공간을 확보하기 위해, 상응하는 여유 heap memory가 필요하다. 이 설정을 조정할 때, 이 부분을 기억하자.

Otheredit

Finally, there are some other considerations to keep in mind:

마지막으로, 기억해야 할 몇 가지 고려 사항이 있다.

  • If you don’t need near real-time accuracy on your search results, consider dropping the index.refresh_interval of each index to 30s. If you are doing a large import, you can disable refreshes by setting this value to -1 for the duration of the import. Don’t forget to reenable it when you are finished!

    검색 결과에 거의 실시간 정확성이 필요하지 않다면, 각 index의 index.refresh_interval 을 30s까지 떨어뜨리는 것을 고려하자. 대규모 import를 하는 경우, import를 하는 동안, 이 값을 -1 로 설정하여, refresh를 비활성화할 수 있다. 끝난 후에 그것을 다시 활성화하는 것을 잊지 말자.

  • If you are doing a large bulk import, consider disabling replicas by settingindex.number_of_replicas: 0. When documents are replicated, the entire document is sent to the replica node and the indexing process is repeated verbatim. This means each replica will perform the analysis, indexing, and potentially merging process.

    대규모 bulk import를 하는 경우, index.number_of_replicas: 0 으로 설정하여, replica를 비활성화하는 것을 고려하자. document를 복제하는 경우, 전체 document는 replica node로 전송되고, 색인 프로세스는 그대로 반복된다. 즉, 각 replica는 분석, 색인, 그리고 잠재적으로 병합 프로세스를 수행한다.

    In contrast, if you index with zero replicas and then enable replicas when ingestion is finished, the recovery process is essentially a byte-for-byte network transfer. This is much more efficient than duplicating the indexing process.

    반대로, replica 없이 색인하고, 색인이 완료된 다음에 replica를 활성화하면, 복구 프로세스는 기본적으로 byte 단위 네트워크 전송이다, 이것이 색인 프로세스를 복제하는 것보다 훨씬 더 효율적이다.

  • If you don’t have a natural ID for each document, use Elasticsearch’s auto-ID functionality. It is optimized to avoid version lookups, since the autogenerated ID is unique.

    각 document가 고유의 ID를 가지고 있지 않다면, Elasticsearch의 자동 ID(auto-ID) 기능을 사용하자. 자동화된 ID는 유일하기 때문에, 버전 조회를 피하는데 최적화되어 있다.

  • If you are using your own ID, try to pick an ID that is friendly to LuceneExamples include zero-padded sequential IDs, UUID-1, and nanotime; these IDs have consistent, sequential patterns that compress well. In contrast, IDs such as UUID-4 are essentially random, which offer poor compression and slow down Lucene.

    자신만의 ID를 사용한다면, Lucene에 친화적인 ID를 선택하도록 하자. 예를 들면, 0으로 채워진 순차적인 ID, UUID-1, nanotime 등이 있다. 이들 ID는 압축이 잘 되는 일관적이고, 연속적인 패턴을 가진다. 반면에, UUID-4 같은 ID는 기본적으로 무작위이다. 그래서, 압축에 약하고, Lucene을 느리게 한다.


'2.X > 7. Administration Monitoring Deployment' 카테고리의 다른 글

7-3-1. Changing Settings Dynamically  (0) 2017.09.23
7-3-2. Logging  (0) 2017.09.23
7-3-4. Delaying Shard Allocation  (0) 2017.09.23
7-3-5. Rolling Restarts  (0) 2017.09.23
7-3-6. Backing Up Your Cluster  (0) 2017.09.23