Before you create an index in an Elasticsearch cluster, you must determine the number of primary shards to be configured for the index based on the actual volume of business data. If you have only a small amount of business data but configure a large number of primary shards for the index, resources may be excessively consumed and QPS or write throughput may be affected. In this case, we recommend that you reduce the number of primary shards configured for the index. This topic describes how to use the _shrink API to shrink an existing index into a new index with fewer primary shards.

Background information

When you use an Elasticsearch cluster, you must take note of the total number of shards configured for indexes in the cluster and shard configuration for each index in the cluster. The larger the total number of shards configured for indexes in the cluster, the more the file handles occupied by the shards, and the more the resources consumed in the cluster. In addition, inappropriate shard configuration such as excessive primary shards affects query and write operations.

If you configure an excessive number of primary shards for an index, you can use the reindex API to reduce the number of primary shards. However, this method requires a long period of time. To reduce time costs, open source Elasticsearch provides the _shrink API. When you use the _shrink API, a shrink operation is performed. You must complete the following steps when you use the _shrink API to reduce the number of primary shards for an index:
  1. Create a new index. The number of primary shards for the new index is less than that for the original index, but the other settings for the new index are the same as those for the original index. Relocate all shards for the original index to the same node in the Elasticsearch cluster and make sure that the reserved disk space for the node is greater than the size of data stored on all primary shards for the original index.
  2. Create hard links to link segments from the original index to the new index.
  3. Recover the new index. This operation is similar to opening a closed index.
The following descriptions provide information about performance tests that are performed on the reindex API and _shrink API:
  • Test environment:
    • Data nodes: five data nodes, each of which offers 8 vCPUs and 16 GiB of memory
    • Data volume: 182 GiB of data stored in an index
    • Number of shards: 30 primary shards for the original index, 5 primary shards for the new index, and no replica shards for both indexes
  • Test results
    Method Consumed time Resource usage
    reindex API 3 hours and 22 minutes The write QPS in the cluster is excessively high, and the resource usage of the data nodes is high.
    _shrink API 15 minutes The computing resource usage of the node on which the shrink operation is performed is high.

Prerequisites

  • The Elasticsearch cluster is healthy, and the load of the cluster is normal.
  • The number of primary shards to be obtained after the shrink operation is evaluated based on the number of data nodes in the Elasticsearch cluster and the disk space of the Elasticsearch cluster. For more information, see Shard evaluation.
  • The original index is in a normal state indicated by the color green.
  • The number of documents stored in the original index does not exceed 2,147,483,519.
  • The Elasticsearch cluster does not contain an index that is named the same as the new index.

Procedure

  1. Log on to the Kibana console of your Elasticsearch cluster and go to the homepage of the Kibana console as prompted.
    For more information about how to log on to the Kibana console, see Log on to the Kibana console.
    Note In this example, an Elasticsearch V7.10.0 cluster is used. Operations on clusters of other versions may differ. The actual operations in the console prevail.
  2. In the upper-right corner of the page that appears, click Dev tools.
  3. On the Console tab of the page that appears, run the following command to disable data write operations for the original index, set the number of replica shards for the original index to 0, and relocate all shards for the original index to the same node in the Elasticsearch cluster.
    In this example, an original index named shrink5 is used. You must replace the name of the original index in the following command based on your business requirements.
    PUT shrink5/_settings
    {
        "index.routing.allocation.require._name": "es-cn-zvp25yhyy000y****-1ab7****-0001",
        "index.blocks.write": true,
        "index.number_of_replicas": 0
    }
                            
    Parameter Description
    index.routing.allocation.require._name The name of the node to which you want to relocate shards. You can run the GET _cat/nodes?v command to obtain the name.
    Note Before you call the _shrink API to shrink an existing index into a new index with fewer primary shards, you must relocate all shards for the original index to the same node in the Elasticsearch cluster.
    index.blocks.write Specifies whether to disable data write operations for the original index. Set this parameter to true. The value true indicates that data write operations are disabled for the original index.
    Note Before you call the _shrink API to shrink an existing index into a new index with fewer primary shards, you must disable data write operations for the original index.
    index.number_of_replicas The number of replica shards for the original index.
  4. Call the _shrink API to shrink the original index into a new index with fewer primary shards.
    The following command provides an example on how to shrink the original index shrink5 that has 30 primary shards to the new index shrink_hk5e_cn that has five primary shards. You must replace the name of the original index and that of the new index in the following command based on your business requirements.
    POST shrink5/_shrink/shrink_hk5e_cn
    {
      "settings": {
        "index.blocks.write": null,
        "index.number_of_shards": 5,
        "index.number_of_replicas": 0,
        "index.routing.allocation.require._name": null
      }
    }
    Parameter Description
    index.blocks.write Specifies whether to disable data write operations for the new index. Set this parameter to null. This way, the settings that are copied from the original index are cleared.
    index.number_of_shards The number of primary shards for the new index.
    Notice
    • After the shrink operation is triggered, the CPU utilization and minute-average load of the node on which the shrink operation is performed are high. We recommend that you shrink indexes during off-peak hours.
    • The number of primary shards for the original index must be greater than that for the new index. The number of primary shards for the original index must be divisible by the number of primary shards for the new index. For example, if the number of primary shards for the original index is 8, the number of primary shards for the new index can be 4, 2, or 1. If the number of primary shards for the original index is 15, the number of primary shards for the new index can be 5, 3, or 1. If the number of primary shards for the original index is a prime number, the number of primary shards for the new index can only be 1.
    index.number_of_replicas The number of replica shards for the new index.
    index.routing.allocation.require._name The name of the node to which you want to relocate shards. Set this parameter to null. This way, the settings that are copied from the original index are cleared.
  5. View the result.
    Call the _cat recovery API to query the index shrink progress. If no recoveries about index shrink are returned and the Elasticsearch cluster is healthy, the index shrink is complete.
    • Query the index shrink progress
      GET _cat/recovery?v&active_only

      If no index that is waiting to be shrunk is displayed in the index column in the returned result, no recoveries about index shrink exist.

    • Query the health status of the Elasticsearch cluster
      GET _cluster/health

      If the returned result contains "status" : "green", the Elasticsearch cluster is healthy.

FAQ

Q: Why are hard links instead of symbolic links used?

A: Hard links ensure the independence of the new index. If you use symbolic links, and you delete the original index after data is written to the new index, data in the new index is also deleted. Hard links ensure that data in the new index is not deleted.