Tune for disk usage

edit

Disable the features you do not need

edit

By default Elasticsearch indexes and adds doc values to most fields so that they can be searched and aggregated out of the box. For instance if you have a numeric field called foo that you need to run histograms on but that you never need to filter on, you can safely disable indexing on this field in your mappings:

PUT index
{
  "mappings": {
    "type": {
      "properties": {
        "foo": {
          "type": "integer",
          "index": false
        }
      }
    }
  }
}

text fields store normalization factors in the index in order to be able to score documents. If you only need matching capabilities on a text field but do not care about the produced scores, you can configure Elasticsearch to not write norms to the index:

PUT index
{
  "mappings": {
    "type": {
      "properties": {
        "foo": {
          "type": "text",
          "norms": false
        }
      }
    }
  }
}

text fields also store frequencies and positions in the index by default. Frequencies are used to compute scores and positions are used to run phrase queries. If you do not need to run phrase queries, you can tell Elasticsearch to not index positions:

PUT index
{
  "mappings": {
    "type": {
      "properties": {
        "foo": {
          "type": "text",
          "index_options": "freqs"
        }
      }
    }
  }
}

Furthermore if you do not care about scoring either, you can configure Elasticsearch to just index matching documents for every term. You will still be able to search on this field, but phrase queries will raise errors and scoring will assume that terms appear only once in every document.

PUT index
{
  "mappings": {
    "type": {
      "properties": {
        "foo": {
          "type": "text",
          "norms": false,
          "index_options": "freqs"
        }
      }
    }
  }
}

Don’t use default dynamic string mappings

edit

The default dynamic string mappings will index string fields both as text and keyword. This is wasteful if you only need one of them. Typically an id field will only need to be indexed as a keyword while a body field will only need to be indexed as a text field.

This can be disabled by either configuring explicit mappings on string fields or setting up dynamic templates that will map string fields as either text or keyword.

For instance, here is a template that can be used in order to only map string fields as keyword:

PUT index
{
  "mappings": {
    "type": {
      "dynamic_templates": [
        {
          "strings": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "keyword"
            }
          }
        }
      ]
    }
  }
}

Watch your shard size

edit

Larger shards are going to be more efficient at storing data. To increase the size of your shards, you can decrease the number of primary shards in an index by creating indices with less primary shards, creating less indices (e.g. by leveraging the Rollover API), or modifying an existing index using the Shrink API.

Keep in mind that large shard sizes come with drawbacks, such as long full recovery times.

Disable _all

edit

The _all field indexes the value of all fields of a document and can use significant space. If you never need to search against all fields at the same time, it can be disabled.

Disable _source

edit

The _source field stores the original JSON body of the document. If you don’t need access to it you can disable it. However, APIs that needs access to _source such as update and reindex won’t work.

Use best_compression

edit

The _source and stored fields can easily take a non negligible amount of disk space. They can be compressed more aggressively by using the best_compression codec.

Force Merge

edit

Indices in Elasticsearch are stored in one or more shards. Each shard is a Lucene index and made up of one or more segments - the actual files on disk. Larger segments are more efficient for storing data.

The _forcemerge API can be used to reduce the number of segments per shard. In many cases, the number of segments can be reduced to one per shard by setting max_num_segments=1.

Shrink Index

edit

The Shrink API allows you to reduce the number of shards in an index. Together with the Force Merge API above, this can significantly reduce the number of shards and segments of an index.

Use the smallest numeric type that is sufficient

edit

The type that you pick for numeric data can have a significant impact on disk usage. In particular, integers should be stored using an integer type (byte, short, integer or long) and floating points should either be stored in a scaled_float if appropriate or in the smallest type that fits the use-case: using float over double, or half_float over float will help save storage.

Use index sorting to colocate similar documents

edit

When Elasticsearch stores _source, it compresses multiple documents at once in order to improve the overall compression ratio. For instance it is very common that documents share the same field names, and quite common that they share some field values, especially on fields that have a low cardinality or a zipfian distribution.

By default documents are compressed together in the order that they are added to the index. If you enabled index sorting then instead they are compressed in sorted order. Sorting documents with similar structure, fields, and values together should improve the compression ratio.

Put fields in the same order in documents

edit

Due to the fact that multiple documents are compressed together into blocks, it is more likely to find longer duplicate strings in those _source documents if fields always occur in the same order.