Performance and subquery limits

Some of our custom JQL functions take a subquery as a first parameter to narrow down the number of issues that will be checked (i.e. parentsOf(), linkedIssuesOf(), issuesInEpics(), …among others). You should enter terms here to restrict the number of issues the function will operate on. Note that, our custom functions DO NOT filter these subqueries further to issues that have the relevant field(s) non-empty so you might also have these into account while crafting your JQL filters.

 

The overall performance of a query will be proportional to the number of issues that are returned by the subquery. This subquery argument can be matching anything from 0 to all issues of your instance which in huge instances could cause some performance issues or even take down your whole instance in the worst scenario.

Taking an example, if you are only interested in issues linked to unresolved Epics within the project EMEA you might go ahead and incorrectly type the following query:

project = EMEA AND issue in issuesInEpics("resolution is not empty")

However although at first glance, this query might looks like trivial it will cause serious performance problems on huge instances. Let’s dive deeper into it…

 

On the given example, provided subquery is "resolution is not empty" as you can see now, there is no project filtering in the subquery itself, project filtering take part in a later stage after issuesInEpics() function is executed. So under this scenario, issuesInEpics() will try to search for any unresolved issue within the system regardless of the project as that’s what you asked the custom function to do. You might solve this problem by narrowing your subquery this way instead:

issue in issuesInEpics("project = EMEA AND resolution is not empty")

This will effectively gather unresolved issues only from project EMEA as now the project filtering take place within the function and not outside of it.

 

Our JQL filter now looks safer indeed, but as we stated at the very beginning of this page these kind of functions DO NOT filter by themselves the results to only issues that have the relevant field(s) non-empty. So forcing the subquery to explicitly only search for Epics within the will improve the overall performance and execution time even further. Refers to the final query shown below:

issue in issuesInEpics("project = EMEA AND type=Epic AND resolution is not empty")

 

How to modify the number of results a subquery can hit? SINCE V3.1.0

To protect your Jira instance from outages or extensive CPU / RAM usage or simply stressing Jira Lucene index to much, our JQL sub-query based functions are (since v3.1.0) protected with a default guardrail. By default, this limit is configured to reject any subquery that hit more than 10,000 issues. However, we believe on freedom, so we leave the final decision to Jira administrators whether the limit should be increased or decreased as they know better than us how much workload they can assume on the instances they administer. The subquery limit can be change by specifying a system property called jqlbooster.subquery.limit

Note that on DataCenter Jira instances running multiple nodes at once, given system property needs to be added on every node present on the cluster.


For example, to decrease the limit to only 5,000 issues, you will need to configure a system property to the following value:

-Djqlbooster.subquery.limit=5000

For exact steps of how to set a system property on Jira instance please refer to official Atlassian documentation pages:

Setting properties and options on startup | Administering Jira applications Data Center 10.3 | Atlassian Documentation

 

In the event someone runs a subquery that reaches the limit, the search won’t run and will throw the following error instead:

image-20240917-181040.png

 

What JQL Functions are affected by these limits?

As for today the following JQL Functions will throw an error and reject to run within your instance if the underlying subquery produces more results than allowed on configured limit: