Leading Practices for Improving Search Response Time

The search response time is the time your Coveo Cloud organization takes to provide results when a user sends a query. The typical search response time is well under one second.

Nonetheless, some factors may imperceptibly or noticeably increase this response time. End users, administrators, or developers can leverage Coveo features that create more complex queries, which then require more resources and therefore notably or significantly increases the search response time. Complex queries can be legitimate and should complete successfully.

You can use this article to troubleshoot longer-than-expected search response times. If following these recommendation does not improve the Coveo Cloud response time, contact Coveo Support.

Search performance or load tests must be planned with and authorized by Coveo (see Can I Conduct a Performance Test on Coveo?).

Assessing Search Response Time

In a Coveo JavaScript Search Framework search page, you can see the total search response time for a query above the corresponding search results.

SearchOptimization-ResponseTime

You can compare this response time to the Coveo Cloud platform-wide average response time as displayed on the Coveo Cloud V1 Status page. Similar statistics for Coveo Cloud V2 is not currently available on the Coveo Cloud V2 Status page.

Response Time Optimization Tips

For Coveo Cloud International Users

Consider a Multi-Region Deployment

The primary deployment region of all Coveo Cloud organizations is in the Eastern United States. This implies that all queries made by end users must travel to that region and back. Thus, end users who are not located in North America typically experience longer search request delays than end users who are. To improve search request time for end users not located in North America, you will likely want to consider deploying over satellite regions (see Multi-Region Deployments).

For All Coveo Cloud Users

Shortness

When making natural language queries, keep them short. Long natural language queries could take more time to process, as they may contain frequent terms matching many irrelevant items. Moreover, since a blank space is considered as an AND Boolean operator by default, a query with many keywords could lead to a long response time or expected results not returned.

Boolean Operators

If possible, when building queries with Boolean operators, use as few OR as possible. A query with an OR operator may return a very large number of results. Since the result ranking process duration is proportional to the number of results to rank, this operator may impact search response time negatively.

Wildcards

Use the wildcard character (*) only when necessary, and only in keywords queries with at least two characters before the wildcard character (see Wildcard Operators and Wildcard Constraints). Since the wildcard character represents one or more characters, finding all possible variations in the index takes time. The more precise the context around the wildcard character, the less items match the query, and the less time it takes to return these items.

For Coveo Cloud Administrators

Precision

  • Make your queries as precise as possible, with as few common or general terms as possible. The less precise the query, the more time it takes to get significant results back.

  • Exact match operators help narrowing your search, as they filter out all items that do not contain the queried expression. However, exact match expressions are more complex to evaluate than regular keywords, since the keyword positions must be loaded to determine whether the keywords are located next to each other.

Simplicity

Simplify your queries as much as possible.

The following expression creates a very complex syntax tree, which leads to many individual node (e.g., @filter=value) evaluations.

@filter = A OR @filter = B OR @filter = C OR @filter = D OR @filter = E OR @filter = F OR @filter = G OR @filter = H OR @filter = I OR @filter = J OR @filter = K OR @filter = L OR @filter = M OR @filter = N OR @filter = O OR @filter = P OR @filter = Q OR @filter = R

The following construction is more efficient:

@filter = (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R)

Comparison operators

  • When searching for the value of a facet field, use the Is Exactly operator (==) (see Add or Edit a Field). When searching for the value of a field that is not used to build a facet, use the Contains operator (=), unless you must match the exact field value.

    You have a web source named MyCompany for your company external website. If you want to filter documents of that source, you can use one of the following filters:

    • @source == "mycompany"

    • @source = "mycompany"

    If you choose the first option, only results whose source field value is exactly mycompany, i.e., only results from your MyCompany source, are displayed. If you choose the second option, all results whose source field value contains mycompany are displayed, such as content from your sources named My Company Employee Portal or MyCompany Customer Database. Content from your MyCompany source is displayed as well.

    You might expect the search with the Is Exactly operator to be slower since it is more restrictive and must make sure that there are no other characters before or after the queried value. When used with a facet field, it is actually faster than a Contains operator search, because only one facet value is loaded in the search results.

    If the field is not used to build a facet, using the Is Exactly operator when not necessary indeed makes the search process slower.

  • Conversely, the Excludes operator (<>), which requires results to have a field value different from that queried, does not leverage the facet structure to speed up the query process. Response time is therefore negatively impacted. Use the NOT operator to optimize your search (see Boolean Operators).

    @author NOT @author == "John Smith" returns results faster than @author <> "John Smith".

For more information, see Comparison Operators.

Field Options

  • Enable the Facet, Multi-value facet, Sortable, and Free text search options only for fields that require such options, since they can impact index performance (see Understanding Fields).

  • Enable the Displayable in results option only for fields whose value you want to return along with the search results. Applying this option to certain fields only minimizes the data to be returned by the server, but the impact on response time is minor.

  • When sorting results on a custom field, enable the Use cache for sort option. Keeping the field in memory improves response time.

  • A field is referred to as a computed field when facet code is edited to implement a calculation using this field. When using computed fields, enable the Use cache for computed fields option. Keeping the field in memory improves response time.

  • Cardinality is the number of different values a field has. Cardinality has a great impact on nested query performance, especially with string fields, as many values must be processed (see Field Types). When using high-cardinality facets (especially string fields), enable the Use cache for nested queries option.

  • When sorting your search results in a custom way, i.e., by field instead of by relevance or date, the response time may not be optimal if the fields are not loaded in cache. Therefore, in the field options, enable both Sortable and Use cache for sort options.

For more information, see Field Types.

Facets

  • The injection depth value is the number of search results that are scanned to find possible facet values. The default value (1,000) may be too low if every item has many values for a single facet field. You can edit the injection depth yourself, but you can also contact Coveo Support to ensure it is adequate, as the larger the injection depth value, the slower the string-field facet (see Editing Components).

  • Some string facet sorting options require more computation than others, which may lead to a longer response time (see Editing Components).

    The Occurrences, AlphaAscending, and AlphaDescending options are the fastest algorithms, while ChiSquare takes longer.

  • Avoid creating string facets displaying many values, as this increases facet loading time (see Editing Components). Default number is 5.

  • If most of the indexed items have a different value for a certain string field, avoid making this field a facet field. Loading many values is resource-demanding, and therefore increases response time. However, if you must have this facet in your search interface, enable the Use cache for nested queries option (see Add or Edit a Field).

  • When configuring range facets, enable cache usage.

For more information, see Using Facets and JavaScript Search Interface Editor.

Advanced Field Queries

  • Although very powerful, advanced field query operators such as *= are more resource-consuming than free-text and comparison operator queries (see Coveo Cloud Query Syntax Reference). Use advanced queries when necessary, and faster operators for better performances. The Use cache for nested queries option can be enabled to cache in memory all the values that occur a single time in the index, which are typically not cached. Even if the setting is named after the nested query feature, the side effect is very beneficial to advanced field operators.

  • Similarly, use wildcards judiciously when making advanced queries. Queries that contain wildcards, when applied to the entire index content, are demanding and might lower performances.

For more information, see Advanced Field Queries.

Search results

  • Exclude irrelevant fields from your search results to improve loading time (see Displayable in search results).

  • The number of requested results has a direct impact on query performance, as loading more items from the index takes more time. Keep the number of returned results as low as possible (see Editing Components). Default number is 10. The higher the number, the larger the quantity of items to return, and the slower the operation. Also, result folding and duplicate filtering will impact performance as well. For folding, you should thus limit the number or folded results to 5 inside each top result. By default, only the first two most relevant children are folded (see Folding Results).

  • Ensure that you do not load a large number or search results per page (see Editing Components). The response time increases with the number of results to load on a page. The default number is typically 10.

Query Pipelines Rules

  • Keep query pipelines as simple as possible. The more rules you configure in the query pipeline, the more time it takes to process.

  • Use as few synonyms as possible in your thesaurus entries (see Thesaurus Leading Practices). Synonyms of each queried term are included in the expanded query, so they can add up to make a much longer query, and therefore increase response time.

  • Use query ranking expressions (QREs) wisely (see Adding and Managing Query Pipeline Ranking Expressions). QREs require a significant amount of processing power, so using many QREs can slow down search performance considerably, especially when many results must be returned. Combined use of Coveo Machine Learning (Coveo ML) Automatic Relevance Tuning (ART) models can slow down the search even more, since ART models are trend-based whereas QREs are based on regular ranking values. ART models and QREs are two resource-demanding features, and leveraging them simultaneously would result in an increased search response time.

  • Use a ranking function rather than many QREs with expressions that only differ by their field value (see Ranking Function).

  • Add stop words to your query pipeline to increase the speed at which natural language queries are processed (see Adding and Managing Query Pipeline Stop Words). These stop words should be extremely common words that appear in all or almost all indexed items.

    a, are, be, for, in, is, of, the, to, you

For more information, see Adding and Managing Query Pipelines.

Nested queries

  • Enable the Use cache for nested queries option for fields you use in nested queries (see Add or Edit a Field). This improves response time since a smaller number of values must transit between queries during evaluation.

    String fields are supported, but nested queries using them have a longer response time than nested queries leveraging numeric field types.

  • If you have a very high cardinality string field (1 million different values or more) on which you perform nested queries, try adding as many constraints as possible in the nested query filter (see Add or Edit a Field). This minimizes the number of values to be transferred from the inner query to the outer query, thus improving response time.

  • Although nested queries support a very high number of nested levels, make nested queries with two levels or less whenever possible. Complex nested queries take more time to execute, thus impacting performance.

Sitecore

  • Connect only one Sitecore farm to your Coveo Cloud organization. A Sitecore farm creates many fields, one security provider, and two sources. Connecting another Sitecore farm to your organization creates more, which impacts performance.

  • If you have a farm of more than one Sitecore server (CM/CD) connected to the same Coveo index, ensure that your farmName value is the same in all the Sitecore instances to avoid having two Sitecore servers battling to update the Coveo index configuration.

Body mapping

If you want to see many or all available metadata in one field, do not configure a free-text searchable computed index field with all the values of all the item fields, as this could reduce performances. Use the Coveo indexed document body feature instead (see Add or Edit a Body Mapping). It is a property on an indexed document rather than a field, it is free-text searchable, and it is also used to create the document Quick View and provide a search result excerpt.

For Developers

constantExpression Queries

constantExpression queries are conditions narrowing search results automatically on top of all user queries.

  • Put the parts of query expressions that seldom change in constantExpression because it is cached.

  • Avoid using date/time operators (now, today, yesterday) in constant expressions, since the date or time they represent change regularly and they cannot be cached. A constantExpression containing such an operator would require to be reevaluated with every query.

If you have already created constant expressions, you may need to optimize them:

  • Enable the Facet option for the involved fields (see Add or Edit a Field and Field Uses)

  • Ensure that you use the Is Exactly operator instead of the Contains operator (see Comparison Operators)

  • Ensure that your query syntax is as simple as possible (see Simplicity)

  • When a constantExpression contains a numeric field with a constant field value, enable the Use cache for numeric queries option.

    • @date > 2017/01/01

    • @size > 1000

    ConstantExpression queries that contain temporal references or other dynamic content cannot be cached, as their values must be regularly recomputed.

    @eventdate > now - 30d

Query Expression Filters

Optimize your query expression filters for performance.

NOT @type=="Bridges Customer Individual" NOT @type=="Bridges Customer Organization"

In this example, the filter will be optimal only if the type field is a facet field. Otherwise, phrase execution will severely impact performance.

$some Query Extension

Use the $some query extension to optimize your natural language queries. This expression lets the index choose the best terms (i.e., least common in the index) before executing the query, and requires that items to return only match a fraction of these best terms.

This query extension is especially useful to isolate relevant words in a long string. By filtering irrelevant terms and querying only the most precise terms of a natural language query, you increase your search performance.

  • The best and the match parameters values can be either absolute or percentage values.

  • Items containing more than the number of keywords required by the match parameter are ranked higher than items containing the exact specified number.

In a customer support context, one could use the $some query extension to find similar support cases without having to read the case description and manually select the words to query. Pasting the entire case description in the $some extension may therefore be more efficient or return better results than a composing regular natural language query.

$some(keywords: this is a simple test to show how to use the extension, best:4, match:50%)

The best parameter dictates that four terms need to be kept among the rarest ones. Then, items to return should match at least 50% of these four terms, meaning that two terms are required. So best could choose to keep simple, test, demonstrate and extension, and items need to match two out of these four terms. Of course, items matching all four terms score higher, as per regular ranking rules.

$valueOfField String

Use the $valueOfField string judiciously. Using this string (often in Salesforce Insight Boxes) executes just as many queries when changing contexts (e.g., switching between cases) because all $valueOfField strings reload at the same time, thus increasing the response time.

Duplicate Filtering

This feature filters out duplicates of items that are at least 85% similar to the original.

The duplicate filtering feature increases response time, especially when applied to many search results. When using this feature, keep the number of returned results as low as possible.

Conversation Folding (or Custom Filtering)

Conversation folding groups results based on the value of a field.

  • The conversation folding feature increases response time, especially when applied to many search results. When using this feature, keep the number of returned results as low as possible.

  • Also keep the number of child items load per parent item (range option) to a minimum, since the parent and child results add up quickly, thus leading to a increased response time.

    Your search result page loads 10 parent results per page, and you set the range option to 20 child item. Your search result page could therefore load up to 210 results per page, i.e., 10 parent results plus up to 20 child results underneath each parent.

  • For an optimal response time, the field based on which results are grouped must contain single word values. If not, the filter is much longer to execute, as phrases must be evaluated.

Queries Per User

Avoid building a search interface that issues more than one search query per actual user search. One user query should execute only one search call to the index, as additional queries would be more demanding and increase response time.

What’s Next

If your response time issues seem to persist, contact Coveo Support for assistance and further investigation.

Recommended Articles