elastic / elasticsearch

Free and Open Source, Distributed, RESTful Search Engine
https://www.elastic.co/products/elasticsearch
Other
1.23k stars 24.85k forks source link

Switch doc_values=true to be the default for non-analyzed string fields #8312

Closed gibrown closed 9 years ago

gibrown commented 10 years ago

We recently started doing a lot of sorting by dates and integer fields on subsets of our 5 billion documents. We are mostly running queries that filter to a few thousand docs and then sorting that subset. Needing to load 5 billion dates into memory for this seemingly common use case make ES feel broken. :)

Heap memory management can be very painful and I think represents a difficult point for new users. Search engines are all about preprocessing data (indexing) so that querying can be fast. In my opinion doc_values accomplishes this better than the current default even if it can be slower in some cases.

FWIW, doc_values is MUCH faster in our use case using 1.3.4.

bobrik commented 9 years ago

@gibrown have you seen increased segment memory usage after switching to doc_values? I've seen 2-8x increase (from 32mb to 70-270mb) per index with 120m events.

clintongormley commented 9 years ago

The JVM heap size is practically limited to 32GB - above this and the JVM can no longer use compressed pointers (resulting in more memory usage for the same data), and garbage collections become slower.

By far the biggest user of the heap for most users is in-memory fielddata, used for sorting, aggregations and scripts. In-memory fielddata is slow to load, as it has to read the whole inverted index and uninvert it. If the fielddata cache fills up, old data is evicted causing heap churn and bad performance (as fielddata is reloaded and evicted again.)

Doc values provide the same function as in-memory fielddata, but the datastructure is written to disk at index time. This results in more disk usage and somewhat slower indexing and mergging (because there is more I/O). Aggregations and sorting are about 20% slower than they are with in-memory fielddata.

The advantages are:

Unfortunately, there is no way to back-fill these values without reindexing. The proposal is to make doc values the default for all fields except analyzed string fields (which are not supported by doc values anyway).

Some users will end up writing much more data than they need, but to be clear: this is a default setting which can be changed as appropriate. It is similar to the fact that we index term positions by default on all analyzed string fields, so as to make phrase queries work out of the box.

Before making this decision, we need to understand the full impact of doc-values-by-default, by running the following tests:

And measuring the following:

We need to do this at large scale with a billion documents, on nodes that are properly tuned (eg ES_HEAP, mlockall etc)

Two further proposals:

bharvidixit commented 9 years ago

@clintongormley what if i enable doc_values=true for the metadata _id field? Will it have some effect? "_id": { "store": true, "index": "not_analyzed", "doc_values": true, "path": "id" }

jpountz commented 9 years ago

@bharvidixit Actually we are also thinking about having doc values enabled on _uid too. This way, random sorting (which mostly merges a seed with a hash of the _uid to be reproducible) would not need to load fielddata on the _uid field (which takes a lot of memory all the time since this field is unique by definition). And it could also help have consistent pagination by tie-breaking on the _uid instead of the internal lucene doc ids (since they are not the same on all copies of a shard).

gibrown commented 9 years ago

Awesome, Thanks!

bobrik commented 9 years ago

:+1:

jknewman3 commented 9 years ago

Is it possible to set eager loading, or something like that, for doc_values? It would be helpful for us to always have the most recently added data in cache. And, yeah, warmers could do it for us. Just wondering if eager applies only to JVM.

rjernst commented 9 years ago

@jknewman3 See discussions on #8693

jknewman3 commented 9 years ago

Ah, that helps a lot. Thanks!

bolee commented 9 years ago

how to set doc_value=true, via api to set every field?

clintongormley commented 9 years ago

@bolee please ask questions like that in the forum: https://discuss.elastic.co/