Faceted navigation performance & troubleshooting

Performance of faceted navigation is blistering fast when configured properly. There are a couple of gotchas to look for if performance is not good enough

You did not define a hippofacnav:limit, and you resultsets are large.

Suppose that you have 1.000.000 documents where there are 250.000 in the current year. Then, the resultset for 'this year' would contain 250.000 documents, which are, well, quite a lot of child nodes. Therefor, it is of major importance, that you define a global resultset limit by hippofacnav:limit. Suppose you want to show the total number of results, and let's say 10 pages of 10 documents. Then, you set a hippofacnav:limit = 100, and you retrieve the actual count (the 250.000) from the parent node. Note by default, we limit the resultset already to 1.000. Thus make sure that you have something like:

Set a limit on the resultset:

hippofacnav:limit = 50

The number of unique facet values is very large for some facet.

For example, suppose my facet is myproject:date and there are 1.000.000 unique timestamps. This would result in a folder containing 1.000.000 sub folders. As you can imagine, this is memory and cpu consuming. A facet which has as value for example a timestamp is not that meaningful anyway. For dates it is better to have for example a facet as myproject:date$year, and then myproject:date$month etc. If your facet however is myproject:author, and there are 10.000 unique authors, you need a different way. Then you can better use the configuration to limit the number of facetvalues shown, this for example by having the hippofacnav:facetnodenames for myproject:author as:

this shows the 10 most common authors:

author${sortby:'count', sortorder:'descending', limit:10}

The frontend retrieves all the documents in the resultset

If you want to show documents 1 to 10 (first page), you do not need to fetch all the documents in the resultset (note that you can order the documents in the resultset on the faceted navigation node, so you should not do that client site). Make sure you only fetch the documents you actually need. For HST2 implementations, this concretely means the following: suppose you have 'HippoFacetChildNavigationBean facetNav'. Now, these are inefficient:

Wrong:

//Do not use, also see API
List<HippoBeanDocument> results = facetNav.getResultSet().getDocuments()

//Do not use, also see API
List<HippoBeanDocument> results = facetNav.getResultSet().getDocuments(0, 10)

But use instead:

Correct:

List<ProductBean> resultset = new ArrayList<ProductBean>();
HippoDocumentIterator<ProductBean> it =
            facetNav.getResultSet().getDocumentIterator(ProductBean.class);
int skip = 0;
it.skip(skip);
while(it.hasNext() && it.getPosition() < 10 + (skip - 1)) {
   resultset.add(it.next());
}

The HippoDocumentIterator is a lazy loading iterator, that only populates those documents that are needed.

You have a range query on a date in your XPath and you have a large data set.

Range queries are very cpu intensive in Jackrabbit. In combining an XPath in faceted navigation, this might become slow. If you can use 'f) Ranges faceted navigation' instead, this has a proper performance. Or make sure you use fast date range queries as described inĀ Fast and Scalable Date Range Searches with Hippo Repository.

You are traversing the faceted navigation tree deeper than needed

If in your code, you are unnecessarily traversing all faceted navigation nodes deeper than necessary, the performance decreases a lot. Make sure you do not traverse more nodes than needed.

You are unnecessarily populating the hippo:resultset for some nodetypes

Depending on your use case, you do not need to populate the hippo:resultset for the hippofacnav:facetnavigation or for the hippofacnav:facetsavailablenavigation : For example, most of the time, you do not need a hippo:resultset on the hippofacnav:facetsavailablenavigation nodes. The performance of the faceted navigation tree becomes better if you indicate that the resultset can be skipped. Skipping the hippo:resultset for the root hippofacnav:facetnavigation node: On the hippofacnav:facetnavigation add the boolean property

<sv:property sv:name="hippofacnav:skipresultsetfacetnavigationroot"
             sv:type="Boolean">
    <sv:value>true</sv:value>
</sv:property>

Skipping the hippo:resultset for the hippofacnav:facetsavailablenavigation node: On the hippofacnav:facetnavigation add the boolean property

<sv:property sv:name="hippofacnav:skipresultsetfacetsavailable"
             sv:type="Boolean">
    <sv:value>true</sv:value>
</sv:property>