7.5. Optimizing the Query Process
Query performance depends on several criteria:
- the Lucene query itself: read the literature on this subject
- the number of object loaded: use pagination (always) or index projection (if needed)
- the way Hibernate Search interacts with the Lucene readers: defines the appropriate reader strategy. For details, refer to Section 4.3, “Reader Strategies”
- caching frequently extracted values from the index: see Section 7.5.1, “Caching Index Values: FieldCache”
7.5.1. Caching Index Values: FieldCache
The primary function of a Lucene index is to identify matches to your queries, still after the query is performed the results must be analyzed to extract useful information: typically Hibernate Search might need to extract the Class type and the primary key.
Extracting the needed values from the index has a performance cost, which in some cases might be very low and not noticeable, but in some other cases might be a good candidate for caching.
What is exactly needed depends on the kind of Projections being used (see Section 7.1.10.5, “Projection”), and in some cases the Class type is not needed as it can be inferred from the query context or other means.
Using the @
CacheFromIndex annotation you can experiment different kinds of caching of the main metadata fields required by Hibernate Search:
import static org.hibernate.search.annotations.FieldCacheType.CLASS; import static org.hibernate.search.annotations.FieldCacheType.ID; @Indexed @CacheFromIndex( { CLASS, ID } ) public class Essay { ...
It is possible to cache Class types and IDs using this annotation:
CLASS: Hibernate Search will use a Lucene FieldCache to improve peformance of the Class type extraction from the index.This value is enabled by default, and is what Hibernate Search will apply if you don't specify the @CacheFromIndexannotation.ID: Extracting the primary identifier will use a cache. This is likely providing the best performing queries, but will consume much more memory which in turn might reduce performance.
Note
Measure the performance and memory consumption impact after warmup (executing some queries). Performance may improve by enabling Field Caches but this is not always the case.
Using a FieldCache has two downsides to consider:
- Memory usage: these caches can be quite memory hungry. Typically the CLASS cache has lower requirements than the ID cache.
- Index warmup: when using field caches, the first query on a new index or segment will be slower than when you don't have caching enabled.
With some queries the classtype won't be needed at all, in that case even if you enabled the
CLASS field cache, this might not be used; for example if you are targeting a single class, obviously all returned values will be of that type (this is evaluated at each Query execution).
For the ID FieldCache to be used, the ids of targeted entities must be using a
TwoWayFieldBridge (as all builting bridges), and all types being loaded in a specific query must use the fieldname for the id, and have ids of the same type (this is evaluated at each Query execution).