Elasticsearch is a very versatile platform, that supports a variety of use cases, and provides great flexibility around data organisation and replication strategies. This flexibility can however sometimes make it hard to determine up-front how to best organize your data into indices and shards, especially if you are new to the Elastic Stack. While suboptimal choices will not necessarily cause problems when first starting out, they have the potential to cause performance problems as data volumes grow over time. The more data the cluster holds, the more difficult it also becomes to correct the problem, as reindexing of large amounts of data can sometimes be required.
Elasticsearch는 매우 다양한 플랫폼으로, 다양한 use case를 지원하며, 데이터 구성 및 복제 정책에 큰 유연성을 제공한다. 그러나 때로는 이러한 유연성이, 특히 Elastic Stack을 처음 접하는 사용자에게, index 및 shard에서 데이터를 효과적으로 구성하는 방법을 미리 결정하기 어렵게 만든다. 그러나 최적화되지 않은 선택은 처음 시작할 때 반드시 문제가 되는 것은 아니지만, 시간이 지나면서 데이터 볼륨이 증가함에 따라 성능 문제가 발생할 가능성이 있다. cluster에 저장된 데이터가 많을수록, 경우에 따라 대용량 데이터의 재색인이 필요할 수 있으므로, 문제를 해결하는 것 또한 어려워진다.
When we come across users that are experiencing performance problems, it is not uncommon that this can be traced back to issues around how data is indexed and number of shards in the cluster. This is especially true for use-cases involving multi-tenancy and/or use of time-based indices. When discussing this with users, either in person at events or meetings or via our forum, some of the most common questions are “How many shards should I have?” and “How large should my shards be?”.
성능 문제를 가지고 있는 사용자를 만나보면, 그 문제가 데이터 색인 방식과 cluster의 shard 수와 관련된 문제로 밝혀지는 것은 드문 경우가 아니다. 이는 특히, 시간 기반(time-based) index에서 multi-tenancy and/or 사용과 관련된 use case에 해당된다. 이벤트 또는 미팅이나 forum을 통해, 직접 사용자와 이를 논의할 때, 가장 흔한 질문 중 몇 가지는 "shard의 수는 몇 개로 해야 하나요?"와 "shard의 크기는 어떻게 해야 하나요?" 이다.
This blog post aims to help you answer these questions and provide practical guidelines for use cases that involve the use of time-based indices, e.g. logging or security analytics, in a single place.
이 블로그 게시물은 이러한 질문에 답하고, 시간 기반 index의 사용과 관련된 use case에 대한 실질적인 지침을 제공하는 것을 돕는 것을 목표로 한다. 예를 들자면, 한 곳에서 logging 또는 보안 분석(security analytics) 같은 것이 있다.
What is a shard?
Before we start, we need to establish some facts and terminology that we will need in later sections.
시작하기에 앞서, 이후 섹션에서 필요한 몇 가지 사실과 용어를 정의할 필요가 있다.
Data in Elasticsearch is organized into indices. Each index is made up of one or more shards. Each shard is an instance of a Lucene index, which you can think of as a self-contained search engine that indexes and handles queries for a subset of the data in an Elasticsearch cluster.
Elasticsearch에서 데이터는 indices로 구성된다. 각 index는 하나 이상의 shard로 이루어진다. 각 shard는 Lucene index의 인스턴스이며, Elasticsearch cluster에서 데이터 하위 집합에 대해 색인하고 query를 처리하는 독립적인 검색 엔진이라 할 수 있다.
As data is written to a shard, it is periodically published into new immutable Lucene segments on disk, and it is at this time it becomes available for querying. This is referred to as a refresh. How this works is described in greater detail in Elasticsearch: the Definitive Guide.
데이터가 shard에 쓰여지면, 그것은 주기적으로 디스크에 있는 새로운 변경 불가능한 Lucene segment가 된다. 그리고 이 시점에 그것은 query가 가능해진다. 이것을 refresh라 한다. 이것이 작동하는 방법은 Elasticsearch: the Definitive Guide 에 자세히 설명되어 있다.
As the number of segments grow, these are periodically consolidated into larger segments. This process is referred to as merging. As all segments are immutable, this means that the disk space used will typically fluctuate during indexing, as new, merged segments need to be created before the ones they replace can be deleted. Merging can be quite resource intensive, especially with respect to disk I/O.
segment의 수가 증가하면, 이들은 주기적으로 더 큰 segment로 통합된다. 이 프로세스를 merge라 한다. 모든 segment는 변경 불가능하므로, 교체될 segment가 삭제되기 전에 새로이 병합된 segment가 생성되어야 하므로, 일반적으로 index시에는 사용된 디스크 공간에 변동이 있다. merge는 특히 디스크 I/O 측면에서, 꽤나 많은 resource를 필요로 한다.
The shard is the unit at which Elasticsearch distributes data around the cluster. The speed at which Elasticsearch can move shards around when rebalancing data, e.g. following a failure, will depend on the size and number of shards as well as network and disk performance.
shard는 Elasticsearch가 cluster에 데이터를 분산하는 단위이다. Elasticsearch가 데이터를 재조정(rebalancing) - 예를 들자면, 장애 발생 후에 - 할 경우 shard를 옮기는 속도는 shard의 수나 크기 뿐만 아니라 network 그리고 디스크 성능에 따라 다를 것이다.
TIP: Avoid having very large shards as this can negatively affect the cluster's ability to recover from failure. There is no fixed limit on how large shards can be, but a shard size of 50GB is often quoted as a limit that has been seen to work for a variety of use-cases. 너무 큰 shard는 피하자. 이것은 cluster의 장애시 복구 능력에 부정적인 영향을 줄 수 있다. shard의 크기에는 고정된 제한이 없으나, 다양한 use-case를 살펴보면, 50GB가 shard 크기의 제한으로 흔히 언급된다. |
Index by retention period
As segments are immutable, updating a document requires Elasticsearch to first find the existing document, then mark it as deleted and add the updated version. Deleting a document also requires the document to be found and marked as deleted. For this reason, deleted documents will continue to tie up disk space and some system resources until they are merged out, which can consume a lot of system resources.
segment는 변경 불가능하므로, document를 update하려면 먼저 Elasticsearch에 기존의 document를 찾은 다음, 삭제된 것으로 표시하고, update된 버전을 추가해야 한다. 마찬가지로 document를 삭제하려면, document를 찾아서 삭제된 것으로 표시해야 한다. 이런 이유로, 삭제된 document는 merge가 끝날때까지 disk 공간과 시스템 resource를 사용하게 되고, 이것은 많은 시스템 리소스를 사용하게 된다.
Elasticsearch allows complete indices to be deleted very efficiently directly from the file system, without explicitly having to delete all records individually. This is by far the most efficient way to delete data from Elasticsearch.
Elasticsearch에서는 명시적으로 모든 record를 개별적으로 삭제하지 않고도, 매우 효율적으로, 직접, 파일 시스템에서 indices를 완전히 삭제할 수 있다. 이것이 지금까지 Elasticsearch에서 데이터를 삭제하는 가장 효율적인 방법이다.
TIP: Try to use time-based indices for managing data retention whenever possible. Group data into indices based on the retention period. Time-based indices also make it easy to vary the number of primary shards and replicas over time, as this can be changed for the next index to be generated. This simplifies adapting to changing data volumes and requirements.
가능한 한 데이터 유지 관리를 위해 시간 기반(time-based indices를 사용하자. 유지 기간을 기준으로 데이터를 indices에 그룹화하자. 시간 기반(time-based) indices는 또한 시간에 따라 primary/replica shard의 수를 변경하는 것이 쉽다. 왜냐하면 이것은 다음에 생성될 index에 대해 변경이 가능하기 때문이다. 이것은 데이터 볼륨이나 요구사항 변경에 맞추는 것이 간단해진다.
Are indices and shards not free?
For each Elasticsearch index, information about mappings and state is stored in the cluster state. This is kept in memory for fast access. Having a large number of indices in a cluster can therefore result in a large cluster state, especially if mappings are large. This can become slow to update as all updates need to be done through a single thread in order to guarantee consistency before the changes are distributed across the cluster.
각각의 Elasticsearch index에 대한 mapping과 state에 대한 정보는 cluster state에 저장된다. 이것은 빠른 액세스를 위해 메모리에 저장된다. cluster가 많은 indices를 가진다는 것은, 특히 mapping이 큰 경우, 결국 큰 cluster state로 이어잔다. 변경 사항이 cluster 전체에 분산되기 전에, 일관성을 보장하기 위해 단일 thread를 통해 모든 update가 수행되어야 하므로, 이런 경우에 update 속도가 느려질 수 있다.
TIP: In order to reduce the number of indices and avoid large and sprawling mappings, consider storing data with similar structure in the same index rather than splitting into separate indices based on where the data comes from. It is important to find a good balance between the number of indices and the mapping size for each individual index.
indices의 수를 줄이고 크고 마구잡이로 확장되는 mapping을 피하기 위하여, 데이터 소스를 기준으로 별도의 indices로 분할하는 것 보다는 동일한 index에 유사한 구조를 가진 데이터를 저장하는 것을 고려하자. indices의 수와 각각의 개별 index에 대한 mapping 크기 사이의 균형을 잘 맞추는 것이 중요하다.
Each shard has data that need to be kept in memory and use heap space. This includes data structures holding information at the shard level, but also at the segment level in order to define where data reside on disk. The size of these data structures is not fixed and will vary depending on the use-case.
각 shard는 메모리에 보관해야 하고 heap 영역을 사용해야 하는 데이터가 있다. 여기에는 shard level에서 정보를 가지고 있는 데이터 구조를 포함하지만, segment level에서 디스크에 데이터가 있는 위치를 정의하기 위한 데아터 구조도 포함한다. 이들 데이커 구조의 크기는 고정되어 있지 않으며, use-case에 따라 다르다.
One important characteristic of the segment related overhead is however that it is not strictly proportional to the size of the segment. This means that larger segments have less overhead per data volume compared to smaller segments. The difference can be substantial.
overhead와 관련된 segment의 한가지 중요한 특징은 그것이 segment 크기에 엄밀히 비례하지 않는 점이다. 즉, 더 큰 segment는 더 작은 segment에 비해 데이터 볼륨 당 overhead가 더 적다. 그 차이는 상당할 수 있다.
In order to be able to store as much data as possible per node, it becomes important to manage heap usage and reduce the amount of overhead as much as possible. The more heap space a node has, the more data and shards it can handle.
node별로 가능한 한 많은 데이터를 저장할 수 있도록 하려면, heap 사용을 관리하고 가능한 한 overhead의 양을 줄이는 것이 중요하다. node가 가진 heap 영역이 많을수록, 더 많은 data와 shard를 처리할 수 있다.
Indices and shards are therefore not free from a cluster perspective, as there is some level of resource overhead for each index and shard.
따라서, indices와 shard는 cluster로부터 자유롭지 않다. 각 index와 shard에 대해 약간의 리소스 overhead가 있기 때문이다.
TIP: Small shards result in small segments, which increases overhead. Aim to keep the average shard size between a few GB and a few tens of GB. For use-cases with time-based data, it is common to see shards between 20GB and 40GB in size.
작은 shard는 작은 segment를 만들어, overhead가 증가한다. shard의 평균 크기를 수 GB에서 수십 GB 정도로 유지하도록 하자. 시간 기반(time-based) 데이터의 use-case에서는 크기가 20 GB에서 40 GB인 shard가 일반적이다.
TIP: As the overhead per shard depends on the segment count and size, forcing smaller segments to merge into larger ones through a forcemerge operation can reduce overhead and improve query performance. This should ideally be done once no more data is written to the index. Be aware that this is an expensive operation that should ideally be performed during off-peak hours.
shard별 overhead는 segment의 수와 크기에 따라 다르므로, forcemerge 작업을 통해, 더 작은 segment를 더 큰 segment로 병합(merge)하면, overhead는 감소하고 query 성능은 향상될 수 있다. 이론적으로 이 작업은 index에 더 이상 데이타가 쓰여지지 않으면 한번 이루어져야 한다. 이론적으로 이 작업은 피크 시간이 아닌 시간에 수행되어야 하는 비싼 작업이다.
TIP: The number of shards you can hold on a node will be proportional to the amount of heap you have available, but there is no fixed limit enforced by Elasticsearch. A good rule-of-thumb is to ensure you keep the number of shards per node below 20 to 25 per GB heap it has configured. A node with a 30GB heap should therefore have a maximum of 600-750 shards, but the further below this limit you can keep it the better. This will generally help the cluster stay in good health.
node가 가질 수 있는 shard의 수는 사용가능한 heap의 양에 비례하지만, Elasticsearch에 의해 적용되는 고정된 제한은 없다. 경험적으로, node별 shard의 수는 설정된 heap의 GB 당 20 ~ 25 개 이하로 유지하는 것이 좋다. 따라서, 30 GB heap을 가진 node는 최대 600~750개의 shard를 가진다. 그러나 한도를 훨신 밑도는 것이 더 좋다. 이것이 일반적으로 cluster를 건강하게 유지하는 데에 도움이 된다.
How does shard size affect performance?
In Elasticsearch, each query is executed in a single thread per shard. Multiple shards can however be processed in parallel, as can multiple queries and aggregations against the same shard.
Elasticsearch에서, 각 query는 shard별로 단일 thread로 실행된다. 그러나, 동일한 shard에 대해 여러 query와 aggregation을 수행할 수 있듯이, 여러 shard가 동시에 처리될 수 있다.
This means that the minimum query latency, when no caching is involved, will depend on the data, the type of query, as well as the size of the shard. Querying lots of small shards will make the processing per shard faster, but as many more tasks need to be queued up and processed in sequence, it is not necessarily going to be faster than querying a smaller number of larger shards. Having lots of small shards can also reduce the query throughput if there are multiple concurrent queries.
즉, caching이 포함되지 않는 경우, 최소 query 대기 시간은 데이터, query 유형 및 shard의 크기에 따라 다르다. 작은 shard를 많이 query하면, shard별 처리 속도는 더 빨라지지만, 더 믾은 작업을 queue에 담고 순서대로 처리해야 하므로, 더 작은 수의 더 큰 shard를 query하는 것 보다 반드시 더 빠르지는 않을 것이다. 작은 shard를 많이 가지고 있으면, 다수의 동시 query가 있는 경우, query 처리량도 감소할 수 있다.
TIP: The best way to determine the maximum shard size from a query performance perspective is to benchmark using realistic data and queries. Always benchmark with a query and indexing load representative of what the node would need to handle in production, as optimizing for a single query might give misleading results.
query 성능 관점에서 shard의 최대 크기를 결정하는 가장 좋은 방법은 실제 data와 query를 통해 benchmark하는 것이다. 단일 query의 최적화가 잘못된 결과를 줄 수 있으므로, 항상 node가 제품에서 처리해야 하는 query와 색인 부하를 가지고 벤치마크하자.
How do I manage shard size?
When using time-based indices, each index has traditionally been associated with a fixed time period. Daily indices are very common, and often used for holding data with short retention period or large daily volumes. These allow retention period to be managed with good granularity and makes it easy to adjust for changing volumes on a daily basis. Data with a longer retention period, especially if the daily volumes do not warrant the use of daily indices, often use weekly or monthly induces in order to keep the shard size up. This reduces the number of indices and shards that need to be stored in the cluster over time.
시간 기반(time-based) indices를 사용할 경우, 각 index는 전통적으로 고정된 기간과 관련되어 있다. 일별 indices는 매우 일반적이고, 보유기간이 짧거나 일별 볼륨이 큰 데이터를 보관하는데 흔히 사용된다. 이를 통해 보존 기간을 정교하게 관리할 수 있고, 매일 변화하는 양을 쉽게 조정할 수 있다. 보존 기간이 더 긴 데이터, 특히 일일 데이터 양이 일별 indices의 사용을 보장하지 않는 경우 shard의 크기가 유지하기 위하여 주별, 월별 indices를 사용한다. 이것은 시간이 지남에 따라 cluster에 저장되어야 하는 indices와 shard의 수를 줄인다.
TIP: If using time-based indices covering a fixed period, adjust the period each index covers based on the retention period and expected data volumes in order to reach the target shard size.
일정한 기간을 대상으로 하는 시간 기반(time-based) indices를 사용할 경우, 목표로 하는 shard 크기에 도달하기 위하여, 보존 기간과 예상되는 데이터 볼륨을 기반으로 각 index를 조정하자.
Time-based indices with a fixed time interval works well when data volumes are reasonably predictable and change slowly. If the indexing rate can vary quickly, it is very difficult to maintain a uniform target shard size.
일정한 시간 간격을 가지는 시간 기반(time-based) indices는 데이터 볼륨이 합리적으로 예측가능하고 천천히 변화할 경우 잘 동작한다. 색인 비율이 빠르게 달라질 수 있다면, 목표로 하는 일정한 shard 크기를 유지가 매우 어렵다.
In order to be able to better handle this type of scenarios, the Rollover and Shrink APIs were introduced. These add a lot of flexibility to how indices and shards are managed, specifically for time-based indices.
이러한 유형의 시나리오를 더 잘 처리하기 위하여, Rollover와 Shrink APIs가 도입되었다. 이들은 indices와 shard를 관리하는 방법에 많은 유연성을 준다. 특히 시간 기반(time-based) indices에 대하여.
The rollover index API makes it possible to specify the number of documents and index should contain and/or the maximum period documents should be written to it. Once one of these criteria has been exceeded, Elasticsearch can trigger a new index to be created for writing without downtime. Instead of having each index cover a specific time-period, it is now possible to switch to a new index at a specific size, which makes it possible to more easily achieve an even shard size for all indices.
rollover index API는 index가 가질 수 있는 document의 수와, document가 index에 쓰여질 최대 기간을 and/or로 지정할 수 있다. 이들 기준 중 하나가 초과되면, Elasticsearch는 중단없이 기록을 위해 새로운 index가 생성되도록 한다. 각 index가 특정 기간을 커버하는 대신, 이제는 특정 크기에서 새로운 index로 전환할 수 있다. 이로 인해, 모든 indices에 대해 일정한 shard 크기가 쉽게 가능하다.
In cases where data might be updated, there is no longer a distinct link between the timestamp of the event and the index it resides in when using this API, which may make updates significantly less efficient as each update my need to be preceded by a search.
데이터가 update될 수 있는 경우에, event의 timestamp와 이 API를 사용하는 경우에 나타나는 index 사이에 더 이상 별개의 link가 없으므로, 각 update가 검색에 선행될 필요가 있을 경우, 업데이트의 효율성이 크게 떨어질 수 있다.
TIP: If you have time-based, immutable data where volumes can vary significantly over time, consider using the rollover index API to achieve an optimal target shard size by dynamically varying the time-period each index covers. This gives great flexibility and can help avoid having too large or too small shards when volumes are unpredictable.
시간에 따라 볼륨이 크게 달라질 수 있는 시간 기반의 변경 불가능한 데이터가 있는 경우, rollover index API를 사용하여 각 index에서 동적으로 변경되는 기간에 따라 최적의 shard 크기를 확보하도록 하자. 이렇게 하면, 유연성이 뛰어나고, 볼륨을 예측할 수 없을 경우 너무 크거니 작은 shard를 가지는 것을 피할 수 있다.
The shrink index API allows you to shrink an existing index into a new index with fewer primary shards. If an even spread of shards across nodes is desired during indexing, but this will result in too small shards, this API can be used to reduce the number of primary shards once the index is no longer indexed into. This will result in larger shards, better suited for longer term storage of data.
shrink index API는 기존의 index를 더 적은 primary shard를 가진 새로운 index로 축소할 수 있다. 색인 중에 node 전반적으로 균일한 shard의 분포가 필요하지만, 이것이 너무 작은 shard로 나타나면, 이 API는, 일단 index에 더 이상 색인이 되지 않는 경우에, primary shard의 수를 줄이는데 사용될 수 있다. 이렇게 하면, shard의 크기가 더 커지고 장기간의 데이터 저장에 더 적합하다.
TIP: If you need to have each index cover a specific time period but still want to be able to spread indexing out across a large number of nodes, consider using the shrink API to reduce the number of primary shards once the index is no longer indexed into. This API can also be used to reduce the number of shards in case you have initially configured too many shards.
각 index가 특정 기간을 커버해야 하지만, 많은 node에 index를 분산하려면, 일단 index에 더 이상 색인이 되지 않는 경우에, primary shard의 수를 줄이는 shrink API의 사용을 고려하자. 이 API는 초기에 너무 많은 shard를 구성한 경우 shard의 수를 줄이는데 사용할 수 있다.
Conclusions
This blog post has provided tips and practical guidelines around how to best manage data in Elasticsearch. If you are interested in learning more, "Elasticsearch: the definitive guide" contains a section about designing for scale, which is well worth reading even though it is a bit old.
이 블로그 게시물은 Elasticsearch에서 데이터를 효과적으로 관리하는 방법에 대한 팁과 효율적인 가이드라인을 제공한다. 더 많은 것을 배우고 싶다면, "Elasticsearch: the definitive guide" 가 확장(scale)에 대한 설계에 대한 내용을 포함하고 있는데, 그 내용은 얼마 안되지만 읽을만 하다.
A lot of the decisions around how to best distribute your data across indices and shards will however depend on the use-case specifics, and it can sometimes be hard to determine how to best apply the advice available. For more in-depth and personal advice you can engage with us commercially through a subscription and let our Support and Consulting teams help accelerate your project. If you are happy to discuss your use-case in the open, you can also get help from our community and through our public forum.
그러나 indices 와 shard에 데이터를 가장 잘 분산시키는 방법에 대한 많은 결정은 use-case에 따라 다르다. 그리고, 때로는 적용할 수 있는 조언을 가장 잘 적용하는 방법을 결정하기가 어려울 수 있다. 보다 깊이 있고 개인적인 조언을 바란다면, subscription을 통해 가능하며, 지원 및 컨설팅팀이 여러분의 프로젝트에 도움을 줄 수 있다. 여러분의 use-case를 공개하여 토론할 수 있다면, community와 공개 forum을 통해 도움을 얻을 수도 있다.