What Are Doc Values in Elasticsearch?

What Are Doc Values in Elasticsearch?

Doc values are the column-style data structure that lets Elasticsearch sort, aggregate, and run scripts quickly without loading everything into memory. This guide explains what they are, how they are built and stored, when to switch them off, and how to keep them healthy in production.

Imagine a huge school register. The teacher keeps two helpers. The first helper can answer, in one second, “Which students have the name Priya?” because there is an alphabetical index at the back of the book. The second helper can answer, in one second, “What are the marks of every student, in order, so I can find the average?” because the marks of all students are written together in one neat column. Elasticsearch needs both helpers. The first one is the inverted index. The second one is called doc values, and it is the hero of this guide.

1What Are Doc Values?

Doc values are an on-disk structure, built when a document is indexed, that stores the value of a field for every document in a column-like layout.

Elasticsearch stores your data as documents. A document is a bundle of fields, such as a product with a name, a price, a category, and a date. When you index that document, Elasticsearch does not just save it once. It builds several helper structures so that different kinds of questions can be answered quickly. Doc values are one of these helpers.

For each field, doc values keep a simple table: for document number one the value is this, for document number two the value is that, and so on. Because all values of one field are stored close together, the engine can read a whole field for many documents very fast. This is exactly what you need when you want to sort results by price, count documents per category, or calculate an average.

Simple Analogy

Think of a spreadsheet. Each row is a document and each column is a field. Doc values are like being able to grab one entire column, say the Price column, without having to open every row and pick out one cell at a time.

i
One Sentence Summary

The inverted index answers “which documents contain this value?” while doc values answer “what is the value of this field in each document?”

Doc values are switched on by default for almost every field type. Most people use them every day without knowing, because every time Kibana draws a bar chart or you sort search results, doc values are doing the work behind the scenes.

2The Problem They Solve: Two Directions of Lookup

Search and analytics look at the same data from opposite directions. One structure cannot be great at both.

The classic search structure is the inverted index. It works like the index at the back of a textbook. You look up a word and you find the pages where it appears. In Elasticsearch, you look up a term and find the list of documents that contain it. This is wonderful for questions such as “find all documents that mention laptop”.

Now suppose you ask a different question: “For the documents that matched, what is the price of each one?” The inverted index is bad at this. It would have to walk through every term of the field to find which terms belong to each document. This is like reading the whole textbook index just to learn which words are on page 57. That is slow.

flowchart LR
  subgraph INV["Inverted index: term to documents"]
    T1["laptop"] --> D1["docs 1, 4, 9"]
    T2["phone"] --> D2["docs 2, 3, 7"]
  end
  subgraph DV["Doc values: document to value"]
    A1["doc 1"] --> V1["price 800"]
    A2["doc 2"] --> V2["price 500"]
    A3["doc 3"] --> V3["price 450"]
  end
        
FIG 1 — The inverted index goes from value to documents, doc values go from document to value

Doc values fix this by storing the opposite direction. Given a document number, you can find its value in one step. And because they are laid out by field, reading the value of one field for a million documents means reading one continuous stretch of data, which computers are very good at.

Simple Analogy

A phone contact list has two useful views. Searching by name to find a number is the inverted index. Scrolling down the list to see every number for a group of friends is doc values. Both views hold the same information, arranged for different jobs.

3Row Thinking Versus Column Thinking

To understand why doc values are fast, it helps to understand the difference between row storage and column storage.

In a row-oriented layout, all the fields of one document are stored together. This is what the original document, called _source, looks like. It is great when you want the whole document back, for example when showing a search result. But it is poor for analysis. To add up all the prices, you would have to open each document, skip past the name, the description, and the date, and pick out the price.

In a column-oriented layout, all values of one field are stored together. To add up all the prices, you read one tight column of numbers and ignore everything else. Data warehouses use this idea for the same reason. Doc values bring the same benefit inside Elasticsearch.

QuestionRow Layout (_source)Column Layout (Doc Values)
Show me the full documentExcellentPoor, must join many columns
Average of one field over a million documentsSlow, must read whole documentsVery fast, reads one column
Sort by one fieldSlowFast
Disk read patternJumping between documentsContinuous stretch of similar values
CompressionMixed data compresses less wellSimilar values compress very well
Simple Analogy

Row storage is a stack of filled-in forms. If you want the ages of everyone, you must pick up every form. Column storage is a single sheet that lists only ages, one under another. Finding the average age takes a glance.

The similarity of values in one column also helps compression. A column of ages contains only small numbers, so it can be squeezed into very few bits per value. A pile of mixed documents cannot be squeezed as tightly.

4Where Doc Values Sit Among Other Data Structures

Elasticsearch and its engine Lucene keep several structures for each field. Doc values are only one member of the family.

Structure 1

Inverted Index

Maps each term to the documents that contain it. Powers full-text and exact match searching.

Structure 2

Points (BKD Tree)

A tree structure for numbers, dates, IPs, and geo points. Powers fast range queries such as price between two limits.

Structure 3

Stored Fields and _source

The original document, kept in row form so that it can be returned in search results and used for reindexing.

Structure 4

Doc Values

Column-style storage of each field’s value per document. Powers sorting, aggregations, and scripts.

Structure 5

Norms

Small numbers stored per text field per document that help calculate the relevance score by field length.

Structure 6

Term Vectors

Optional per-document lists of the terms and positions inside a field, used for special features like highlighting.

StructureDirectionBest At
Inverted indexTerm to documentsFinding documents by value or word
PointsValue range to documentsNumeric and date range filters
Stored fields / _sourceDocument to whole documentReturning complete documents
Doc valuesDocument to field valueSorting, aggregating, scripting

Because each structure takes disk space and index time, Elasticsearch lets you decide per field which ones to keep. A field that you only ever search and never sort or aggregate does not need doc values. A field that you only ever aggregate and never search does not need the inverted index. Understanding this table is the key to designing lean mappings.

5What Uses Doc Values?

Whenever Elasticsearch needs the value of a field for many documents at once, it reaches for doc values.

Sorting

When you sort results by price, date, or name, Elasticsearch reads the sort field’s value for each matching document from doc values, then orders them. Without doc values, sorting on that field is not possible in the normal way.

Aggregations

Counting documents per category, calculating averages, drawing histograms over time, finding the top terms, and computing percentiles all read the values of a field across the matching documents. They are the biggest users of doc values, and they power almost every chart in Kibana.

Scripting

When a script needs the value of a field, for example to compute a discounted price or a custom score, the fast way is to read it from doc values. Reading from the original document is much slower.

Returning Field Values

A search request can ask for specific fields to be returned straight from doc values instead of from the original document. This is useful for fields that you do not keep in the source or when you want the normalized value.

Index Sorting and Some Queries

An index can be physically ordered by a field using doc values, and some range or lookup queries can use doc values when that is cheaper than using other structures.

i
Rule of Thumb

If you want to sort, aggregate, or use a field in a script, that field needs doc values. If you only ever search on it, it does not.

6Which Field Types Have Doc Values by Default?

Almost all field types come with doc values switched on. There are a few important exceptions.

Field TypeDoc Values by Default?Note
keywordYesThe standard type for sorting and aggregating strings
Numbers (integer, long, float, double and others)YesStored as sorted numeric columns
date and date_nanosYesStored as whole numbers of milliseconds or nanoseconds
booleanYesStored as small numbers, zero and one
ipYesStored as a fixed-width binary form
geo_pointYesStored as encoded coordinates
textNoAnalyzed text is not suited to columns; use a keyword sub-field
annotated_textNoSame reason as text
binaryNoOff by default, can be enabled

The most important exception is the text field. Text is broken into many small terms by an analyzer, such as splitting a sentence into words. A document’s text field therefore does not have one simple value, but many pieces. Sorting or aggregating on those pieces is rarely what anyone wants. So text fields do not build doc values.

Simple Analogy

A price tag has one clear value, so you can line up all price tags in a column. A paragraph of description has no single value to line up. If you want to group products by an exact label, you keep a separate label tag, which is the keyword sub-field.

!
Common Mistake

Trying to sort or aggregate on a text field produces an error that suggests using a keyword sub-field. The fix is not to turn on the memory-hungry alternative. The fix is to use the keyword version of the field.

7How Doc Values Are Written

Doc values are not made when you search. They are made when you index, which is why they cost disk space and a little indexing time.

When a document arrives, Elasticsearch reads each field, and for every field with doc values enabled, it adds the value to an in-memory buffer for that field. The document also goes into the buffers for the inverted index and the other structures. These buffers are held by the shard, which is one Lucene index.

Periodically, the shard performs a refresh. During a refresh, the buffers are written to disk as a new segment. A segment is a small, complete, read-only mini index. The doc values of the fields for the documents in that segment are written as part of it. Once written, a segment is never changed.

sequenceDiagram
  participant C as Client
  participant S as Shard
  participant B as In-memory Buffers
  participant G as New Segment on Disk
  C->>S: Index a document
  S->>B: Add terms to inverted index buffer
  S->>B: Add value to doc values buffer
  S->>B: Keep original document
  Note over S,B: More documents arrive
  S->>G: Refresh writes buffers as a segment
  G->>C: New documents become searchable
        
FIG 2 — Doc values are built in memory at index time and written into a segment at refresh

Merges rewrite columns

Over time a shard collects many small segments. A background process called a merge combines several small segments into one larger segment and then removes the old ones. During a merge, the doc values columns of the old segments are read and rewritten as one bigger column. This keeps the number of segments low, and it also physically removes values of deleted documents.

i
Why It Matters

Because doc values are made at index time and stored per segment, changing the mapping of an existing field to add doc values does not create them for old documents. You would need to reindex your data to rebuild them.

8The Column Types Inside Lucene

Under the hood, Lucene knows a small number of doc values shapes. Every Elasticsearch field maps onto one of them.

Lucene TypeWhat It HoldsUsed For
NUMERICOne whole number per documentSingle-valued numbers and dates in low-level use
SORTED_NUMERICZero, one, or many whole numbers per document, kept sortedNumeric, date, boolean, and geo fields in Elasticsearch
BINARYAn arbitrary block of bytes per documentSpecial fields such as binary and some internal uses
SORTEDOne string per document, stored as a position in a sorted listSingle-valued strings in low-level use
SORTED_SETMany strings per document, as positions in a sorted listkeyword fields in Elasticsearch

You do not have to remember these names to use Elasticsearch. But they explain many behaviors. Numbers of all kinds are turned into whole numbers. A price stored as a decimal is converted into a number pattern that keeps its order. Dates become a count of milliseconds since a starting date. Strings become positions in a sorted list of unique strings, which is the ordinal trick that we explore next.

Conversion

Dates

Saved as a long number of milliseconds since the epoch, or nanoseconds for the nanosecond date type.

Conversion

Booleans

Saved as zero for false and one for true, which packs into a single bit per value in a dense column.

Conversion

Decimals

Floating point numbers are turned into bit patterns that sort in the same order as the numbers themselves. Scaled decimals are stored as whole numbers multiplied by a factor.

Conversion

Geo Points

Latitude and longitude are packed into a single encoded number so a point takes very little space.

9Ordinals: The Clever Trick for Strings

Strings are big and repeated. Ordinals let doc values store them cheaply and compare them quickly.

Imagine a field called country with a million documents. Only about two hundred different countries exist, but the same names repeat again and again. Storing “United States” a hundred thousand times would waste space. So doc values do something clever. They first build a sorted list of the unique values in the segment. Then, for every document, they store only the ordinal, which is the position of its value in that list.

flowchart LR
  subgraph L["Sorted unique list in the segment"]
    O0["0: Brazil"]
    O1["1: India"]
    O2["2: Japan"]
  end
  D1["doc 1"] --> O1
  D2["doc 2"] --> O0
  D3["doc 3"] --> O1
  D4["doc 4"] --> O2
        
FIG 3 — Each document stores a small position number that points into a sorted list of unique strings

This has three big benefits. First, space: a small number replaces a long string. Second, speed of comparison: to sort documents by country, you compare small numbers, not strings, because the list is sorted, so smaller ordinals always mean earlier alphabetical order. Third, speed of grouping: to count documents per country you can count how many times each ordinal appears, and only look up the actual string names at the end for the few groups that survive.

Simple Analogy

A school gives each class a number instead of writing the full class name on every student’s card. Card 3 means “Class 3-B”. To sort cards by class, you sort numbers. To count students per class, you count numbers. You only read the full class name when you print the final report.

i
Bonus

Because the list is sorted, doc values give a natural sorted order for free. Nothing has to sort the strings again at query time.

10Global Ordinals and Why They Live in Memory

Ordinals are local to a segment. To combine results across segments, Elasticsearch needs one shared numbering.

Each segment has its own sorted list of unique values, and the ordinal numbers mean different things in different segments. Ordinal 1 might be “India” in one segment and “Japan” in another. When a terms aggregation runs across a whole shard, it needs to add up counts from all segments. Comparing segment ordinals directly would be wrong.

To fix this, Elasticsearch builds global ordinals. This is a mapping that translates every segment’s local ordinals into one numbering that is valid across the whole shard. With global ordinals, a terms aggregation can count in a single simple array, one slot per unique value, no matter how many segments exist.

flowchart TD
  S1["Segment A local ordinals"] --> G["Global ordinals map"]
  S2["Segment B local ordinals"] --> G
  S3["Segment C local ordinals"] --> G
  G --> AGG["One counting array for the whole shard"]
        
FIG 4 — Global ordinals translate many local numberings into one shard-wide numbering

The catch: they are built at query time and stored on the heap

Global ordinals are not saved in the segment files. They are built on demand, the first time an aggregation needs them, and then kept in memory on the JVM heap. When a refresh creates new segments, the old global ordinals are no longer valid and must be rebuilt at the next aggregation. On a busy index that refreshes every second, and with a field that has many unique values, this rebuilding can make the first aggregation after each refresh noticeably slow.

Simple Analogy

Imagine several classes each numbering their students from one. To make a school-wide report, you need a single school-wide roll number list. Building that list takes time, and if a new class joins, you must rebuild it.

!
Eager Option

A field setting called eager global ordinals tells Elasticsearch to build the mapping during refresh instead of waiting for the first search. This moves the cost from the unlucky first user to the background refresh. It suits fields that are aggregated often, but it makes refreshes heavier, so use it thoughtfully.

11Multi-Valued Fields: What Happens to Order and Duplicates

A field can hold a list, such as several tags on one article. Doc values treat lists in a special way.

When a document has many values in one field, the doc values store all of them for that document, but not exactly as you sent them. The values are stored in sorted order, not in the order you provided. For string values, repeated copies of the same value are also merged into one. For numbers, repeated values are kept.

This is usually harmless, since aggregations and sorting do not care about the original order. But it surprises people who read values back from doc values and expect the same list they sent. The original list is still safe in the _source, which is the place to read from when order matters.

Value SentStored in _sourceRead from Doc Values
Tags: red, blue, redred, blue, redblue, red
Numbers: 9, 3, 3, 79, 3, 3, 73, 3, 7, 9
Simple Analogy

Your original shopping note lists items in the order you thought of them, with repeats. The store’s stock system lists the same items alphabetically without repeating names. Both are correct for their own purpose.

Sorting and aggregating on lists

When you sort on a field that holds many values, you must decide which value represents the document. Elasticsearch lets you choose the smallest or the largest, or for numbers, the sum, average, or median. In aggregations, a document with many values is counted once for each of its distinct values, so a document tagged with two labels appears in two buckets.

i
Design Tip

If your business logic needs the exact original order of a list, keep it in the source or in a nested structure, and do not rely on doc values to preserve it.

12Compression and the Disk Layout

Doc values look big on paper, but smart encoding keeps them small.

A column of similar values compresses very well. Lucene uses several techniques, chosen automatically for each column, depending on what the values look like.

Technique

Bit Packing

If all values in a block fit into, say, seven bits, each one is stored with only seven bits instead of a full sixty-four.

Technique

Offset From Minimum

Values are stored as the distance from the smallest value in the block, which keeps the numbers small.

Technique

Common Divisor

If every value is a multiple of the same number, such as timestamps in whole seconds stored as milliseconds, the divisor is saved once and only the small multiples are stored.

Technique

Lookup Table

If a column has only a few different values, the values are listed once and each document stores a tiny table position.

Technique

Sparse Storage

When most documents have no value for a field, only the documents that do have one are recorded, so missing values cost almost nothing.

Technique

Block Layout

Data is cut into blocks so that reading or skipping to a document does not need reading everything before it.

Simple Analogy

If you are writing down the height of a whole class, you can write “150 plus” at the top and then only note small differences like 2, 5, or 9. You use far less ink than writing 152, 155, 159 in full for each child.

On disk, a segment stores doc values in two kinds of file. One holds the actual data, and a small companion file holds the metadata that says where each field’s column begins and how it is encoded. You rarely touch these directly, but they show up when you analyze disk usage per field.

i
Practical Result

Well-shaped numeric and keyword fields often take only a small part of the total index size. The heavy items are usually the original source and the inverted index of long text fields.

13Memory: Why Doc Values Do Not Fill the Heap

This is the most famous advantage of doc values. They live on disk and rely on the operating system, not on the Java heap.

Elasticsearch runs inside the Java Virtual Machine, which has a limited memory area called the heap. If too much data lives there, garbage collection pauses grow and the node can even crash with an out of memory error. Doc values avoid this problem. The files are memory-mapped, which means the operating system treats them as if they were part of memory, loading pieces from disk when needed and keeping the popular pieces in its page cache.

flowchart TD
  Q["Aggregation or sort needs a column"] --> P{"Is the needed part in the OS page cache?"}
  P -->|"Yes"| F["Read at memory speed"]
  P -->|"No"| L["Operating system loads it from disk"]
  L --> F
  F --> R["Result returned, no big heap allocation"]
        
FIG 5 — The operating system, not the Java heap, manages the cache of doc values

This is why guides say to leave about half of a machine’s memory free for the operating system instead of giving everything to the heap. That free memory becomes the page cache, and a bigger page cache means more of your doc values sit in fast memory. The machine can handle far more data than its heap alone could hold.

Simple Analogy

Instead of carrying all the books in your backpack, which is the heap, you keep them on library shelves, which is the disk, and a helpful librarian, which is the operating system, keeps the most requested books on the front desk. Your backpack stays light.

!
System Setting

Because these files are memory-mapped, the operating system must allow a large number of memory maps per process. Elasticsearch checks this at startup in production mode, and a low limit is a common cause of nodes refusing to start. Follow the system configuration guidance for your platform.

14Doc Values Versus Fielddata

Fielddata is the old alternative that still exists for text fields. Knowing the difference saves many outages.

Text fields have no doc values. If you insist on sorting or aggregating on a text field, Elasticsearch can build something called fielddata. It does this by reading the entire inverted index of that field in reverse, turning terms back into document-to-term data, and holding the result on the Java heap. This is slow to build and uses a lot of memory, since it must hold every term of every document in that field.

For this reason, fielddata is turned off by default on text fields. It is a safety feature. If you really need it, you can switch it on, but the better route is almost always to add a keyword sub-field and use its doc values instead.

PointDoc ValuesFielddata
Built whenAt index time, saved in segmentsAt query time, on first use
Stored whereOn disk, cached by the operating systemOn the Java heap
Works onKeyword, numbers, dates, and similar typesText fields
Startup costNone at query timeLarge delay on first use
RiskExtra disk spaceHeap pressure and circuit breaker trips
DefaultOnOff for text
Simple Analogy

Doc values are like a printed class list prepared in advance. Fielddata is like asking every student to stand up and announce their name in reverse order, then writing it all on a giant whiteboard that must be memorized by the teacher. It works once, but it is exhausting.

i
Best Approach

Map a field twice when you need both behaviors. The text version is used for full-text search, and the keyword sub-field is used for sorting and aggregating. This is what the default dynamic mapping does for strings.

15Walk-Through: How an Aggregation Reads Doc Values

Let us follow a simple aggregation, counting products per category, from request to answer.

sequenceDiagram
  participant C as Client
  participant Co as Coordinating Node
  participant Sh as Each Shard
  participant Seg as Segments
  C->>Co: Search with terms aggregation on category
  Co->>Sh: Run the query and the aggregation on your shards
  Sh->>Seg: Find matching documents using the inverted index
  Seg->>Sh: Read category ordinals for those documents from doc values
  Sh->>Sh: Count per ordinal, translate to names for top groups
  Sh->>Co: Send partial counts
  Co->>Co: Merge counts from all shards
  Co->>C: Final buckets
        
FIG 6 — The inverted index finds the documents, doc values supply the field values, and the coordinating node merges

Step by step

1

Find the Matches

The query part of the request uses the inverted index or points to build the set of matching document numbers in each segment.

2

Read the Column

For each matching document, the aggregation reads the category’s ordinal from doc values. Only that field’s column is touched.

3

Count in a Simple Array

Using global ordinals, the shard adds one to the slot of each ordinal. No strings are compared during counting.

4

Resolve Names for the Winners

Only the top groups have their ordinals turned back into text. This saves work for groups that will be thrown away.

5

Merge Across Shards

Each shard sends its partial counts, and the coordinating node combines them into the final answer.

!
Accuracy Note

Because each shard sends only its top groups, terms aggregations can be slightly approximate when there are many unique values. The response includes error information you can read, and you can ask each shard for more groups to reduce the error.

16Walk-Through: Sorting

Sorting looks simple, but it depends on doc values in a specific way.

By default, search results are sorted by relevance score, which is calculated from the inverted index and norms. When you ask for a sort by a field, such as price or date, each shard must obtain that field’s value for the candidate documents. It reads them from doc values, keeps the best ones in a small priority list, and sends only that list to the coordinating node. The coordinating node merges the lists from all shards and returns the final page.

Sorting on a keyword field compares ordinals inside each segment, which is fast. Sorting across segments and shards uses the real values for the final comparison. Numeric and date sorting compares plain whole numbers, which is the fastest of all.

Sorting on Missing Values

Some documents have no value in the sort field. Sorting lets you choose whether they go first or last. Sparse doc values make it cheap to know which documents are missing a value.

Sorting on Many-Valued Fields

When a document has several values, you choose which one counts, such as the smallest, the largest, or a computed average. The choice changes the order of the results, so decide it deliberately.

Deep Pagination

Asking for page one hundred thousand of a sorted result forces every shard to gather and sort a huge list. Doc values are fast, but this pattern is still expensive, and search-after style paging is the recommended alternative.

i
Speed Tip

If your index is pre-sorted on the same field you sort by, Elasticsearch can stop early once it has found enough top results. This is the idea behind index sorting, which we cover shortly.

17Scripts and Runtime Fields

Scripts let you compute new values on the fly. Doc values decide how fast that computation runs.

A script is a small program that runs inside Elasticsearch, often written in the built-in Painless language. Scripts are used to calculate custom scores, build values for sorting, or define runtime fields, which are fields computed at query time instead of at index time.

To read a field’s value inside a script, you have two options. The first reads from doc values, which is fast because the value is right there in a column. The second reads from the original document source, which is slow because the document must be fetched and its structure parsed for every match. Modern scripting interfaces steer you towards doc values wherever possible, and they fall back to the source only when a field has no doc values.

Script Reads FromSpeedWorks When
Doc valuesFastThe field has doc values enabled
_sourceSlowAlways, but expensive for many documents
Stored fieldSlowThe field was stored separately
Simple Analogy

Calculating a discount for every product is easy if prices are in one column, since you just walk down the column. It is painfully slow if you must open each product’s full file, find the price line, and read it every single time.

!
Hidden Dependency

If you turn off doc values on a field to save space, any script, runtime field, or dashboard that relied on it may become slow or fail. Always search your saved dashboards and scripts before removing doc values.

18Returning Values: docvalue_fields, Fields, and _source

There are several ways to get a field back in a search response. They read from different places and behave differently.

Option 1

_source

Returns the original document exactly as you indexed it, with the original order and duplicates of lists.

Option 2

Fields Option

Returns selected fields in a clean, consistent form. It reads mostly from the source and applies mapping rules, so it handles things like aliases and formats well.

Option 3

Doc Value Fields

Returns the value as stored in doc values, which is the indexed, normalized form. Lists appear sorted, and formatting can be requested, such as a date format.

Option 4

Stored Fields

Returns fields that were separately marked as stored. Rarely needed now since the source covers most cases.

Returning fields from doc values can be handy when you do not want to fetch and parse the whole source, or when you want the value as the engine sees it, for example to check what actually got indexed. The trade-off is that the values are normalized. A date returns in the format you request, and a list returns sorted, without duplicates for strings.

i
Debugging Idea

If aggregation results look different from what you expect, compare the source with the doc value fields for one document. The difference often reveals a mapping or conversion issue.

19Doc Values and Queries

Doc values are mainly for sorting and aggregations, but they can quietly help queries too.

Numeric and date range filters are normally answered by the points structure, which is a tree built for range lookups. Points are excellent when the range is selective and the rest of the query is broad. But there is a case where they are not the best choice. If the query already has another very selective condition that leaves only a handful of documents, it is cheaper to check just those few documents’ values in doc values than to walk the whole tree.

Lucene has a smart query type for this. It looks at the cost of each approach for the current situation and chooses between the points structure and doc values on the fly. Elasticsearch uses it for range queries on suitable fields, so you get the better of the two without doing anything.

flowchart TD
  RQ["Range filter on price"] --> C{"Is another clause already very selective?"}
  C -->|"No, range does most filtering"| PT["Use points tree"]
  C -->|"Yes, few candidates remain"| DV["Check candidates with doc values"]
  PT --> M["Matching documents"]
  DV --> M
        
FIG 7 — Elasticsearch can pick between points and doc values for a range filter depending on cost

Doc values only fields

You can switch off the searchable index of some field types while keeping doc values. Such a field is stored only for sorting and aggregations. In modern versions, some of these fields can still be searched through doc values, but slowly, because every document’s value must be checked one by one. This is useful for fields that you rarely filter on but that you do want to chart.

!
Not a Free Lunch

Searching through doc values scans values one by one, so it is fine for small result sets or rare queries but not suitable for heavy filtering on large indices. Keep the searchable index on fields that you filter by often.

20Index Sorting and Doc Values

You can ask Elasticsearch to arrange the documents inside each segment in a chosen order. Doc values are what make this possible.

Normally, documents inside a segment are stored in the order they arrived. With index sorting, you choose one or more fields, and documents are reordered by those fields when segments are written and merged. The sort fields must have doc values, because that is where the engine reads the values to sort by.

The benefit shows up when your searches sort on the same fields. Since the documents are already in order, a search can stop after reading the first few matches in each segment, because everything after them would sort later. This is called early termination, and it can save a lot of time for queries that want only the top results. Sorted data also tends to compress better, because similar values sit next to each other.

Benefits

  • Faster top-N sorted searches through early termination
  • Better compression as similar values cluster together
  • Predictable ordering for consistent result sets

Costs

  • Slower indexing and merging, since documents must be reordered
  • The sort settings cannot be changed after the index is created
  • Only helps when queries actually sort by those fields
i
When to Consider

Use index sorting when a small number of well-known sort patterns dominate your traffic. Do not add it by habit, since the indexing cost applies to every document.

21When and Why to Disable Doc Values

Doc values cost disk space and a little indexing time. For some fields, the cost buys nothing.

You can set the doc values option to false for a field in the mapping. The field then builds no column. It saves disk space, and it shortens indexing slightly. But the field can no longer be sorted, aggregated, or used in scripts through doc values. This is a trade you should make only on purpose.

Good Reasons to Disable

  • The field is only ever searched, never sorted, aggregated, or scripted
  • The field is a long identifier or token used only for exact lookups
  • Disk usage analysis shows the column is large and never used
  • You have a huge index where every saved gigabyte matters

Bad Reasons to Disable

  • You are guessing that a field is unused without checking dashboards
  • The saving is tiny compared with other costs
  • You might want to chart it later, since re-enabling needs a reindex
  • Scripts or runtime fields depend on it
ANTI-PATTERN-01 Avoid
Problem

A team disables doc values on many fields at once to reduce disk use, without checking what queries and dashboards use them.

Why It’s Harmful

Dashboards break, scripts become slow, and the only fix is reindexing all the data, which can take days on a large index.

Correct Approach

Measure disk use per field, review real queries, disable only clearly unused fields, and test on a copy of the index first.

!
Cannot Be Changed In Place

The doc values setting cannot be changed on an existing field. To add doc values back, you create a new index with the right mapping and reindex your data into it.

22Choosing Between Keyword, Text, and Numeric Types

The type you pick decides which structures a field gets. That makes mapping design a doc values decision.

DataGood ChoiceWhy
Product descriptiontext with optional keyword sub-fieldFull-text search; doc values only from the keyword part if needed
Category, status, country, tagkeywordExact values, grouping, sorting, all from doc values
Price, quantity, temperaturenumeric typeRange filters use points, math uses doc values
Order id, user id, codekeywordOnly exact lookups are needed, keyword is often faster than numeric for this
TimestampdateRange filters and time histograms both work well
Email or URL with only lookupskeyword, possibly without doc valuesSaves space if never aggregated

A common trap is storing identifiers, such as order numbers, as numbers just because they look like numbers. If you never do math or ranges on them, a keyword field is usually a better fit. Exact match lookups on keyword are simple and fast, and you avoid paying for the range-oriented points structure that you do not use.

i
Long Strings

Very long keyword values are a problem. There is a maximum size for a single term, and huge values also bloat doc values. Use the ignore-above setting to skip indexing values longer than a limit, so that one odd document does not cause errors.

23The Cost Model: Disk, Indexing Speed, and Memory

Every design choice has a price. Here is what doc values cost you, and where those costs appear.

Disk
Each enabled field adds a compressed column per segment
Index Time
Values are encoded and written during refresh and merge
Heap
Only global ordinals for string aggregations live here

Disk. Doc values add to the size of every segment. The amount depends on how many fields you have, their types, and how much the values compress. Low-cardinality fields with repeated values are extremely small. High-cardinality fields, such as unique identifiers, are much bigger, since every value is different and ordinals do not help.

Indexing speed. Building the columns takes some processor time, and writing them makes segments larger, which makes flushing and merging slightly heavier. For most workloads this cost is small compared with the cost of the inverted index, but for extremely write-heavy pipelines with hundreds of fields, it adds up.

Memory. The column data itself is served by the page cache, so it competes for free operating system memory rather than the heap. The heap holds only global ordinals and temporary structures used during aggregations.

Simple Analogy

Keeping a separate column for every attribute is like keeping a separate register for each subject in a school. It costs paper and effort to maintain, but it makes any subject-wise report instant.

i
Balance

The default of enabling doc values everywhere is a sensible choice because analytics needs are hard to predict. Optimize only after you have measurements.

24Performance Tuning Checklist

Follow these steps in order when aggregations or sorting feel slow or when disk use grows too fast.

1

Measure First

Use the disk usage analysis to see how much space each field takes, split by structure. Use the search profile to see where time goes in a slow request.

2

Check the Field Types

Make sure fields you aggregate on are keyword or numeric, not text with fielddata, and that identifiers are not needlessly numeric.

3

Give the Page Cache Room

Keep enough free memory outside the heap so hot columns stay cached. Do not oversize the heap.

4

Tame Global Ordinals

For frequently aggregated string fields on busy indices, consider eager global ordinals, and consider a slower refresh interval to reduce rebuilds.

5

Reduce Cardinality

Aggregating on fields with millions of unique values is heavy. Consider bucketing values, using a cardinality estimate, or aggregating on a coarser field.

6

Prune Unused Columns

For new indices, disable doc values on fields proven never to be sorted, aggregated, or scripted. Apply the change through a new mapping and reindex.

7

Consider Structure Changes

Use index sorting for dominant sort patterns, and force merge read-only indices to reduce segments, which makes global ordinals cheaper and columns more compact.

!
Force Merge Caution

Merging down to one segment is best for indices that no longer receive writes, such as older time-based indices. Doing it on an index that is still being written to creates very large segments that are expensive to keep merging.

25Monitoring, Logging, and Metrics

You cannot manage what you cannot see. Elasticsearch gives several views into doc values and their side effects.

What You Want to KnowWhere to LookWhat It Tells You
How much disk each field usesThe analyze index disk usage operationSize of doc values versus inverted index versus stored fields, per field
Heap used by global ordinals and fielddataNode stats and the cat fielddata viewWhich fields hold memory and how much
Breaker tripsNode stats for circuit breakersRequests refused for using too much memory
Slow aggregationsThe search profile and slow logsTime spent building ordinals and collecting values
Segment count and sizeSegments and index stats viewsWhether merges keep up
Page cache healthOperating system metrics for free and cached memory, and disk readsWhether columns are served from memory or disk

Warning signs

A sudden rise in disk reads on nodes that answer aggregations suggests that the page cache is too small for the working set of columns. A growing fielddata size on a text field suggests that someone switched on fielddata and should be redirected to a keyword sub-field. Repeated slow first aggregations after refresh suggest global ordinals being rebuilt too often.

i
Alert Ideas

Alert on circuit breaker trips, on heap use of fielddata beyond a small threshold, and on aggregation latency for your most important dashboards. These catch doc values problems before users complain.

26Security Considerations

Doc values hold real data. Hiding a field in one place does not hide it everywhere.

Many teams try to protect sensitive fields by leaving them out of the returned source. But if that field has doc values, its values still exist in columns and can be revealed by aggregations, sorting, or scripts unless access is restricted in a proper way. For example, someone who cannot see a salary field in results might still learn the salary range through a histogram.

Control 1

Field Level Security

Use role definitions to grant access only to allowed fields. Restricted fields are hidden from searches, aggregations, and returned results for that role.

Control 2

Document Level Security

Restrict which documents a role can see, so aggregations only count the allowed ones.

Control 3

Do Not Rely on Source Filtering

Excluding a field from the source hides it from returned documents only. It does not remove it from doc values.

Control 4

Protect the Disk

Use encryption at rest for data directories, since segment files contain the raw column data.

!
Think in Structures

A field lives in several structures at once. A security plan must cover all the ways to reach it, not just the way that returns whole documents.

27Common Errors and How to Read Them

Most doc values problems show up as a small set of familiar messages and symptoms.

SymptomLikely CauseFix
Error saying fielddata is disabled on a text fieldSorting or aggregating on textUse the keyword sub-field or add one
Aggregation fails on a keyword field with doc values offDoc values were disabled in the mappingCreate a new index with doc values on and reindex
Circuit breaker for fielddata tripsFielddata enabled on a large text fieldSwitch to keyword doc values, or lower the load
First dashboard load after refresh is slowGlobal ordinals rebuiltConsider eager global ordinals or a slower refresh
Long keyword values rejected or skippedTerm size limit reachedUse ignore-above or shorten the value
Node fails to start with memory map limit messageOperating system limit too lowRaise the memory map limit as documented
Disk usage far above expectationMany high-cardinality fields with doc valuesAnalyze disk usage, prune unused fields
Simple Analogy

Reading these errors is like reading warning lights on a car dashboard. Each light points to one system. Once you learn the few common lights, most problems are found in minutes.

28Doc Values in Newer Features

As Elasticsearch grows, more features lean on doc values. Knowing this helps you plan ahead.

Time Series Data Streams

Special indices for metrics rely heavily on doc values, since metrics are mostly numbers that are aggregated over time. Their design encourages compact columns and index sorting by dimensions and time.

Synthetic Source

Newer versions can skip storing the original source and instead rebuild it from doc values and other stored data when it is needed. This saves large amounts of disk. The trade-off is that the rebuilt document may differ slightly, for example lists may come back sorted, which connects directly to what we learned about multi-valued doc values.

Runtime Fields

Fields computed at query time read the columns of other fields. Fast columns mean fast runtime fields, so good doc values design supports flexible schemas.

Query Language for Analytics

Newer query languages that focus on tabular results read many columns for many documents in bulk. Column-friendly doc values are what make this style of analysis efficient.

The direction is clear. Elasticsearch is moving from being a pure search engine towards being a combined search and analytics engine, and the column structure is at the center of that shift. Details of these features change between versions, so check the documentation for the version you run.

29Design Patterns That Work

These habits keep mappings healthy and analytics fast.

Explicit Mappings for Important Indices

Define fields and types on purpose instead of accepting guesses. This prevents text fields where keywords were needed and avoids accidental fields that add columns nobody uses.

Text Plus Keyword Multi-Fields

Use a text field for searching and a keyword sub-field for sorting and grouping when a field needs both. Add ignore-above to the keyword part.

Keyword for Identifiers

Store ids, codes, and labels that are only compared for equality as keywords, not as numbers.

Dynamic Templates for Control

Use templates so that new string fields become keywords or have doc values disabled according to your naming rules, which limits surprise columns.

Field Budget

Set limits on the number of fields per index to stop mapping explosions, since every extra field can add columns and enlarge the cluster state.

Lifecycle-Based Optimization

Keep fresh indices flexible and optimize older read-only ones by merging segments, which shrinks columns and makes aggregations cheaper.

30Anti-Patterns to Avoid

These are the mistakes that appear in real incidents involving doc values and their relatives.

ANTI-PATTERN-02 Avoid
Problem

Enabling fielddata on large text fields so that aggregations work.

Why It’s Harmful

It loads huge amounts of data into the heap, slows garbage collection, and can trip circuit breakers or crash nodes.

Correct Approach

Use a keyword sub-field and its doc values, or restructure the data so that the analysis field is a proper keyword.

ANTI-PATTERN-03 Avoid
Problem

Aggregating on unique identifier fields with millions of values, such as a terms aggregation on a request id.

Why It’s Harmful

Global ordinals become huge and slow to build, memory use spikes, and results are rarely useful to a human.

Correct Approach

Use a cardinality estimate to count unique values, or filter first so that the aggregation covers only a small set.

ANTI-PATTERN-04 Avoid
Problem

Giving almost all machine memory to the Java heap.

Why It’s Harmful

Doc values live in the operating system page cache. Starving it forces constant disk reads, and a large heap also brings longer pauses.

Correct Approach

Keep the heap at most half of the memory and under the compressed pointer limit, leaving the rest for the operating system.

ANTI-PATTERN-05 Avoid
Problem

Letting dynamic mapping create hundreds of fields from unpredictable keys, such as using user-supplied names as field names.

Why It’s Harmful

Every field can add columns, structures, and cluster state size. This leads to slow updates, high disk use, and unstable clusters.

Correct Approach

Model variable keys as values inside a fixed structure, or use the flattened type, and limit total fields per index.

ANTI-PATTERN-06 Avoid
Problem

Using scripts that read from the original source for every document in large aggregations.

Why It’s Harmful

Each match requires fetching and parsing a whole document, which multiplies the cost of the search many times over.

Correct Approach

Read from doc values in scripts, or compute the value at index time and store it as a real field.

31Best Practices and Common Mistakes

A short checklist to keep nearby when designing mappings.

Best Practices

  • Leave doc values on unless you have measured a reason to switch them off
  • Use keyword or numeric fields for anything you sort or aggregate on
  • Keep enough operating system memory free for the page cache
  • Use disk usage analysis before making pruning decisions
  • Test mapping changes on a copy and reindex on purpose
  • Merge segments of read-only indices to save space and speed up aggregations

Common Mistakes

  • Turning on fielddata for text instead of adding a keyword field
  • Disabling doc values without checking dashboards and scripts
  • Assuming doc values preserve list order and duplicates
  • Ignoring the cost of high-cardinality fields
  • Hiding sensitive fields only by excluding them from the source
  • Over-sizing the heap and starving the page cache
i
A Good Question to Ask

For every field, ask: will I search it, sort it, aggregate it, script it, or only return it? The answers tell you exactly which structures the field needs.

32Advantages and Trade-Offs

Doc values are a fine design, but no design is free of trade-offs.

Advantages

  • Fast sorting, aggregations, and script access from a column layout
  • Kept out of the Java heap, so large data does not cause memory crises
  • Built at index time, so there is no long delay on the first query
  • Compress well through several encoding techniques
  • Ordinals make string grouping and sorting cheap
  • Enabled by default, so analytics works out of the box

Disadvantages / Trade-offs

  • Extra disk space and indexing work for every enabled field
  • Not available for analyzed text fields
  • Cannot be added to existing data without reindexing
  • Multi-valued fields lose original order and string duplicates
  • Global ordinals on the heap can be slow to rebuild on busy indices
  • Speed depends on the operating system page cache being large enough

The message is one of balance. For most fields, the small cost of doc values is worth the power they give. For a small number of large, purely searchable fields, switching them off is a fair and useful saving.

33Real-World Scenarios

These stories show doc values at work in typical systems.

Online Store Category Filters

A shop shows filters on the side of the search page, such as brand, color, and size, each with a count. Every count is a terms aggregation over keyword fields, served from doc values. The price slider uses a numeric range and a histogram, also from columns. Sorting by price low to high is another read of the price column.

Log Dashboards

A team charts errors per service per minute. The service name is a keyword, the timestamp is a date, and the status is a keyword. The dashboard aggregates over them using doc values. When they add a new dashboard on a field mapped as text, it fails, and the fix is a keyword sub-field in the next index.

A Disk Saving Project

An operations team analyzes disk usage and finds that a long request token field takes a large share of every index, though nobody ever charts it. They create a new mapping with doc values off for that field, reindex, and reclaim a meaningful share of storage without affecting any dashboard.

Slow First Chart of the Morning

A busy index refreshes every second, and its main dashboard groups by a keyword field with many unique values. Each refresh invalidates global ordinals, so the first chart after each refresh is slow. The team enables eager global ordinals on that field and lengthens the refresh interval, and the dashboard becomes smooth.

Sensitive Salary Field

A company removes salary from returned documents, but analysts can still build a histogram on it. The security team switches to field level security so the field is invisible to analyst roles in every operation.

“Search finds the documents. Doc values explain what is inside them.”

34A Field-by-Field Design Workshop

Theory becomes useful when you apply it. Let us design the mapping of a small product catalog and decide, field by field, which structures each one needs.

Suppose we are building a search page for an online shop. Customers will type words to find products, filter by brand and price, sort by price or newest first, and see counts of products per brand and per category. We also chart daily orders for the sales team. For each field, we ask five questions: will we search it, sort it, aggregate it, script it, or only show it?

FieldUsed ForSuggested TypeDoc Values Decision
Product titleFull-text search, shown in resultstext, with a keyword sub-field if alphabetical sort is wantedOnly the keyword sub-field has them
Long descriptionFull-text search onlytextNone, since it is text
BrandFilter, count per brandkeywordKeep on, since counts need them
Category pathFilter, count per categorykeywordKeep on
PriceRange filter, sort, price histogramscaled float or floatKeep on
Created dateSort by newest, daily chartsdateKeep on
Stock keeping codeExact lookup onlykeywordConsider off if never charted or sorted
Image addressOnly shown, never searchedkeyword with index offConsider off, and keep it in the source
Tags listFilter, count per tagkeywordKeep on, remember lists come back sorted
Warehouse locationDistance sort, mapgeo_pointKeep on

Reading the table

Notice how few decisions are hard. Most fields keep their defaults. The two interesting cases are the fields that are only shown and the fields that are only used for exact lookup. For the image address, we do not even need the searchable index, and we can skip doc values too, because the value is always taken from the source. For the stock keeping code, we keep the searchable keyword index, but we might switch doc values off if disk analysis shows the column is large and no dashboard charts it.

Simple Analogy

Packing for a trip means asking what each item is for. A raincoat is for rain, a charger is for the phone. If an item has no purpose on this trip, it stays at home and your bag stays light. A field with no sort, aggregation, or script purpose can leave its column at home.

i
Workshop Habit

Write this kind of table for every important index before you create it. It takes twenty minutes and prevents months of pain, because mappings are the hardest thing to change later.

35Dynamic Mapping and What It Does to Doc Values

If you do not write a mapping, Elasticsearch guesses one. The guesses decide your doc values without you noticing.

When a document contains a field that the index has never seen, dynamic mapping decides its type from the value. A whole number becomes a long. A decimal number becomes a float. A true or false value becomes a boolean. A string that looks like a date in a common format becomes a date. Any other string becomes a text field with an added keyword sub-field.

That last rule is the most important for doc values. The text part supports full-text search and has no doc values. The keyword sub-field has doc values and is used when you sort or aggregate. To prevent giant values from causing problems, the automatic keyword sub-field skips strings longer than a fixed limit, so very long strings have no keyword form and no doc values.

Incoming ValueGuessed TypeDoc Values?
A whole numberlongYes
A decimal numberfloatYes
true or falsebooleanYes
A date-like stringdateYes
Any other stringtext plus keyword sub-fieldOnly on the sub-field, and only for short values
A number written as a stringtext plus keyword, unless numeric detection is onOnly on the sub-field
!
Guess Risk

The first document decides the type. If the first value of a field is a number and a later one is a word, the later document may be rejected. If the first value is a small whole number, the field becomes a long even if later values are decimals, which can silently cut them. Dynamic mapping is convenient for exploration but risky for production.

Tighten With Templates

Use an index template with dynamic rules, for example mapping every new string as a keyword only, or turning off dynamic creation completely for unknown fields. This gives you control over which columns are built without writing every field by hand.

36Doc Values in Object, Nested, and Flattened Fields

Real documents are rarely flat. Doc values follow the shape of your data in ways that are worth understanding.

Object fields

When a document contains an object, for example an address with a city and a postal code, Elasticsearch flattens it into dotted field names such as address city and address postal code. Each of these leaf fields is a normal field with its own doc values column. There is no special structure for the object itself.

This has a subtle effect on lists of objects. If a document has a list of two products, each with a color and a size, the colors go into one column and the sizes into another. The link that says this color belongs to this size is lost, because doc values store each field independently.

Nested fields

The nested type solves the lost link. Every object in the list is indexed as its own hidden document that sits next to the parent. Each hidden document has its own doc values, so the color and size of one product stay together. Aggregations can then be run on the nested documents with a special nested aggregation, and results can be joined back to the parent with a reverse nested step.

flowchart TD
  P["Parent order document"] --> N1["Hidden nested doc: color red, size M"]
  P --> N2["Hidden nested doc: color blue, size L"]
  N1 --> C1["Own doc values columns"]
  N2 --> C2["Own doc values columns"]
        
FIG 8 — Each nested object is a separate hidden document with its own doc values columns

Flattened fields

The flattened type is for objects with an unpredictable number of keys, such as user-defined labels. The whole object is indexed as one keyword-like field, and its doc values keep the key together with the value. This avoids creating a new column per key, which protects you from mapping explosion, at the price of supporting only keyword-style behavior on the values.

ShapeDoc Values LayoutWatch Out For
Plain objectOne column per leaf fieldLists of objects lose the link between their parts
NestedColumns per hidden documentEvery nested object adds a document to the count and the cost
FlattenedOne shared column holding key and value togetherValues behave like keywords only
i
Choose With Care

Nested documents are powerful but they multiply the number of Lucene documents, and with them the doc values work. Use nested only when you must keep the link between fields inside a list.

37Metrics, Cardinality, and Other Aggregations on Doc Values

Not all aggregations behave alike. Knowing how the common ones read doc values helps you predict cost.

Metric

Sum, Average, Min, Max

Read the numeric column for the matching documents and combine the numbers in a single pass. Very cheap and predictable.

Metric

Percentiles

Read the numeric column and feed each value into a compact summary that estimates the percentile. Memory use stays small no matter how many documents match.

Metric

Cardinality

Counts distinct values approximately. It hashes each value read from doc values and keeps a small sketch, so memory does not grow with the number of unique values.

Bucket

Terms

Groups by unique values and counts, using global ordinals on string fields. Cost grows with the number of unique values.

Bucket

Date Histogram

Reads the date column and places each value into a time bucket by rounding. Cost depends on the number of documents and the number of buckets.

Bucket

Composite

Groups over several fields and lets you page through all groups in order, which suits exports and large group counts.

Execution choices for terms

A terms aggregation on a string field has more than one way to run. The usual way uses global ordinals, which is excellent when many documents match and the number of unique values is moderate. The other way works directly with the string values and skips building global ordinals. It is better when very few documents match, because it avoids paying the cost of building the shared numbering for the sake of a handful of documents. You can hint which way to use, but the default is usually right.

Simple Analogy

If you must count votes from a whole city, preparing a roll number list is worth it. If you only need to count votes from three people, just ask them their names directly. The ordinal list is a great tool when the crowd is big.

!
Approximate by Design

Cardinality and percentiles give estimates, not exact answers. The error is small and controllable, and it is the reason they stay fast and light on memory even for huge data sets.

38Doc Values Across Deletes, Updates, Merges, and Snapshots

Segments never change, so how do doc values behave when documents are updated or deleted? The answer is worth knowing.

When you delete a document, Elasticsearch does not erase it from the segment. It marks the document as deleted in a small side record. The document’s values remain in the doc values column until the next merge, but searches and aggregations skip the marked documents, so they do not appear in results.

An update is really a delete plus a new index operation. The old version is marked deleted, and the new version is written into the newest segment with fresh doc values. So a workload that updates the same documents very often produces many deleted entries and many small segments, and the merge process has to work hard to clean them up.

1

Delete or Update

The old document is only marked as deleted. Its column entries are still on disk but ignored by queries.

2

New Version Indexed

For an update, the new version lands in a new segment with its own fresh values in each column.

3

Merge Cleans Up

When segments are merged, the columns are rewritten without the deleted documents, and disk space is reclaimed.

4

Global Ordinals Reset

Since segments changed, the shard-wide ordinal mapping is rebuilt the next time an aggregation needs it.

Snapshots and restores

Snapshots copy segment files, and doc values are simply part of those files. Restoring a snapshot brings the columns back exactly as they were, with no rebuilding step. This is also true for searchable snapshots, where the segment files stay in object storage and pieces are fetched into a local cache when needed. Aggregations on such data read the columns through that cache, so the first read of a column can be slower than later reads.

i
Practical Note

Space taken by deleted documents inside doc values is only freed by merges. If disk use looks higher than your live data suggests, check the count of deleted documents and the segment state.

39Capacity Planning With Doc Values in Mind

Doc values influence how you size disks, memory, and node tiers. Plan for them explicitly.

For disk, do not guess. Index a realistic sample of your data into a test index with your intended mapping, then run the disk usage analysis. It shows how many bytes each field uses for doc values, the inverted index, stored fields, and other structures. Multiply the result to your full data volume, and add room for replicas and for merges, which temporarily need extra space.

For memory, remember there are two separate budgets. The heap needs to be large enough for the normal operation of the node and for global ordinals of your busiest keyword fields. The rest of the machine memory, outside the heap, is the page cache, which decides how many columns can be served without touching the disk. If your dashboards hit only the last day of data, the working set is small and a modest cache is enough. If they scan months of data, you need a much bigger cache or faster disks.

TierDoc Values BehaviorPlanning Advice
HotConstant writing of new columns, frequent reads of recent columnsFast disks and strong memory for the page cache
WarmRead-only, mostly aggregation readsMerge segments, moderate memory, larger cheaper disks
ColdRare reads, compact segmentsFocus on storage cost
FrozenColumns fetched from object storage into a local cacheExpect slower first reads, plan cache size by working set

Example Thinking

A team stores a year of logs. Dashboards mostly look at the last seven days, and a monthly report scans the last thirty. They give the hot nodes enough free memory to cache a week of the most used columns, merge older indices into few segments, and accept that the monthly report reads more from disk. They do not oversize the heap, since the heap does not hold the columns.

i
Working Set Idea

The number that matters most is the working set: the columns your important queries actually read in a typical hour. Size the cache for that, not for the total data on disk.

40How Doc Values Compare With Columnar Formats Elsewhere

The idea behind doc values is not unique to Elasticsearch. Seeing the same idea elsewhere makes it easier to remember.

Analytics databases and data lake formats have used column storage for many years. Files designed for analytics store each column together and compress it, so a query that needs only three columns out of a hundred reads only those three. This is exactly the advantage doc values bring to Elasticsearch. The main difference is that doc values live inside a search engine, next to the inverted index, so you get search and analytics on the same data without moving it.

System TypeMain LayoutStrengthWeakness
Classic relational row storeWhole rows togetherFetching and updating single recordsScanning one field across huge tables
Analytics column storeColumns togetherScans and aggregations at scaleSingle record lookups and frequent updates
ElasticsearchInverted index plus doc values plus sourceText search and analytics on the same dataHeavier storage than a pure column store
Simple Analogy

A general shop that also has a small warehouse can sell to walk-in customers and also handle bulk orders, but it will not be as cheap as a pure warehouse for bulk orders. Elasticsearch is that flexible shop, and doc values are its warehouse aisle.

This comparison also explains a design boundary. If your main need is scanning many billions of rows for simple sums, and you have no need for full-text search, a dedicated analytics store might cost less. If you need both text search and fast grouping on the same records, Elasticsearch gives you both from a single copy of the data.

i
Right Tool

Knowing the layout helps you pick the right system for a workload, and it helps you explain to your team why a certain aggregation is fast while a certain full document fetch is comparatively slow.

41Myths About Doc Values

Some ideas about doc values are repeated so often that people treat them as facts. Let us test the most common ones.

MYTH-01 False
The Belief

Doc values are only needed for aggregations, so sorting does not use them.

The Reality

Sorting, aggregations, and scripts all read doc values. Sorting on a field without doc values is not possible in the normal way.

What To Do

Treat any field that appears in a sort clause as a doc values field, and keep the option enabled for it.

MYTH-02 False
The Belief

Doc values are a cache that Elasticsearch builds while searching.

The Reality

Doc values are built at index time and saved in the segment files. The thing that is built while searching is global ordinals, which is a separate helper on top of doc values.

What To Do

Do not expect a warm-up step to create doc values. Plan for the disk cost at indexing time, and plan for the ordinal cost at query time.

MYTH-03 False
The Belief

A bigger heap always makes aggregations faster because the data must be in memory.

The Reality

The column data is served from the operating system page cache. A heap that is too large takes memory away from that cache and makes garbage collection slower.

What To Do

Size the heap for the node’s needs and leave the rest of the machine memory to the operating system.

MYTH-04 False
The Belief

Text fields can be aggregated if I just wait long enough, because Elasticsearch will figure it out.

The Reality

Text fields have no doc values. The only route is fielddata, which is off by default because it fills the heap and can bring a node down.

What To Do

Add a keyword sub-field and aggregate on that. It is faster, safer, and uses the column structure designed for the job.

MYTH-05 False
The Belief

Hiding a field from the returned source also hides it from analysis.

The Reality

The source and the doc values are separate structures. Removing a field from one does not remove it from the other, so it can still be grouped, sorted, or read by a script.

What To Do

Protect sensitive fields with field level security, and do not rely on source filtering as a security control.

MYTH-06 False
The Belief

Doc values double the size of my index, so I should turn them off everywhere.

The Reality

Columns compress well, and for most fields they are a small share of the total size. The original source and long text inverted indices are usually much larger. Turning off doc values broadly destroys your analytics for a small saving.

What To Do

Measure with the disk usage analysis, and prune only the specific large fields that nobody sorts, aggregates, or scripts.

“Doc values are cheap when they are used and wasteful only when they are forgotten.”

42Frequently Asked Questions

Q1Are doc values on by default?

Yes, for nearly all field types, including keyword, numbers, dates, booleans, IP addresses, and geo points. The main exceptions are text and annotated text fields, and the binary type.

Q2Why can’t I sort or aggregate on a text field?

Text is analyzed into many terms, so a document has no single value to sort by, and text fields build no doc values. Use a keyword sub-field for sorting and grouping.

Q3Are doc values stored in memory or on disk?

They are stored on disk in the segment files, and the operating system caches the active parts in its page cache. They do not take up the Java heap, except that global ordinals for string aggregations are built on the heap.

Q4What is the difference between doc values and the inverted index?

The inverted index maps values to the documents that contain them, and doc values map each document to its value. The first is for finding documents, the second is for reading values across many documents.

Q5Can I add doc values to an existing field?

Not in place. Doc values are built at index time, so you need a new index with the desired mapping, and you reindex the data into it.

Q6Do doc values keep the original order of my list?

No. Values in a multi-valued field are stored sorted, and duplicate strings are merged. The original order stays in the source.

Q7What are global ordinals and why do they matter?

They are a shard-wide numbering of the unique values of a keyword field, built at query time from each segment’s local ordinals. They make terms aggregations fast but can be slow to rebuild after each refresh.

Q8Should I disable doc values to save space?

Only on fields that you are certain are never sorted, aggregated, or scripted. Measure disk use first, check dashboards and scripts, and remember that turning them back on means reindexing.

Q9Why do fields with unique values take so much space?

Ordinals only save space when values repeat. With unique values, every document needs its own entry in the sorted list, so the column is large.

Q10Is fielddata the same as doc values?

No. Fielddata is built at query time on the heap from the inverted index, mainly for text fields, and it is disabled by default. Doc values are built at index time and live on disk.

Q11Do doc values affect search relevance?

Not directly. Relevance comes from the inverted index and norms. Doc values matter when you sort, aggregate, or use scripts, including custom scoring scripts that read field values.

Q12How can I see how much space doc values use?

Use the analyze index disk usage operation, which reports the size of each structure for each field, including doc values, the inverted index, and stored fields.

Q13Can a field be searched if it has only doc values?

In modern versions, some field types can be searched through their doc values when the searchable index is turned off, but it is slow because values are checked one by one. Keep the normal index on fields that you filter by often.

Q14Does a bigger Java heap make aggregations faster?

Usually not. Doc values are served by the operating system cache. A heap that is too big steals memory from that cache and lengthens garbage collection pauses.

Q15Why does my node complain about memory maps at startup?

Because segment files are memory-mapped, the operating system limit on the number of memory maps must be high enough. Raise it according to the setup guide for your platform.

Q16Do excluded source fields still exist in doc values?

Yes. Excluding a field from the source does not remove its doc values. If the field is sensitive, use field level security to control access.

43Summary and Key Takeaways

Doc values are the column-style structure that Elasticsearch builds at index time to answer one question quickly: what is the value of this field in each document? They power sorting, aggregations, scripts, and returning of normalized values. They are stored in segment files, compressed with several clever techniques, and served through the operating system page cache rather than the Java heap. Strings use ordinals, and global ordinals connect segments for fast grouping. Like the school register in our opening story, Elasticsearch works best when both helpers are present: the inverted index to find, and doc values to measure.

Key Takeaways

  • Doc values are a column store — they map each document to its field value, the opposite direction of the inverted index.
  • They are on by default — for keyword, numeric, date, boolean, IP, and geo fields, but not for analyzed text.
  • Built at index time, stored per segment — so they cost disk and indexing effort, and cannot be added to old data without reindexing.
  • Off the heap, in the page cache — leave enough memory to the operating system so that hot columns stay fast.
  • Ordinals make strings cheap — global ordinals speed up terms aggregations, but they live on the heap and are rebuilt after refresh.
  • Use keyword sub-fields, not fielddata — this is the safe way to sort and aggregate on strings that also need full-text search.
  • Disable only with evidence — measure disk use per field, check dashboards and scripts, and remember that security must cover doc values too.