Leading Practices for Improving Search Response Time
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 doesn’t 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
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 isn’t 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 aren’t 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’ll likely want to consider deploying over satellite regions (see Multi-Region Deployments).
For All Coveo Cloud Users
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.
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.
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
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 don’t 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.
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 = 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)
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 isn’t used to build a facet, use the Contains operator (
=), unless you must match the exact field value.
You have a web source named
MyCompanyfor 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
sourcefield value is exactly
mycompany, i.e., only results from your
MyCompanysource, are displayed. If you choose the second option, all results whose
sourcefield value contains
mycompanyare displayed, such as content from your sources named
My Company Employee Portalor
MyCompany Customer Database. Content from your
MyCompanysource is displayed as well.
You might expect the search with the Is Exactly operator to be slower since it’s 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’s actually faster than a Contains operator search, because only one facet value is loaded in the search results.
If the field isn’t 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, doesn’t 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.
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 aren’t loaded in cache. Therefore, in the field options, enable both Sortable and Use cache for sort options.
For more information, see Field Types.
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’s 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.
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.
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 don’t 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.
For more information, see Adding and Managing Query Pipelines.
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.
If you want to see many or all available metadata in one field, don’t 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’s a property on an indexed document rather than a field, it’s free-text searchable, and it’s also used to create the document Quick View and provide a search result excerpt.
constantExpression queries are conditions narrowing search results automatically on top of all user queries.
Put the parts of query expressions that seldom change in
constantExpressionbecause it’s cached.
Avoid using date/time operators (now, today, yesterday) in constant expressions, since the date or time they represent change regularly and they can’t be cached. A
constantExpressioncontaining such an operator would require to be reevaluated with every query.
If you have already created constant expressions, you may need to optimize them:
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)
constantExpressioncontains a numeric field with a constant field value, enable the Use cache for numeric queries option.
@date > 2017/01/01
@size > 1000
ConstantExpressionqueries that contain temporal references or other dynamic content can’t 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
$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.
matchparameters values can be either absolute or percentage values.
Items containing more than the number of keywords required by the
matchparameter 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%)
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
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 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.
This feature filters out duplicates of items that are at least 85% similar to the original.
Conversation Folding (or Custom Filtering)
Conversation folding groups results based on the value of a field.
Also keep the number of child items load per parent item (
rangeoption) 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
rangeoption 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.
If your response time issues seem to persist, contact Coveo Support for help and further investigation.