Filter query is quite slow in 8.11 compared to 7.13

There seems to be a big performance difference for a bool query between 7.13 and 8.11 when there are no matches. The query in question has two terms filters, one of them very selective and the other is very broad.

In 7.13, the profiler suggests that when the first filter doesn't match any documents, the second filter is almost bypassed, whereas in 8.11 that is not the case.

To demonstrate the issue I have created an index with just two fields

{
	"settings": {
		"index": {
			"number_of_shards": 1,
			"number_of_replicas": 1
		}
	},
	"mappings": {
		"properties": {
			"refKey": {
				"type": "keyword"
			},
			"country": {
				"type": "keyword"
			}
		}
	}
}

and ingested one million documents where refKey is unique and country is randomly chosen from 26 strings. I also did a force merge to create a single segment to rule out any segment count variance.

Then I used jmeter to query the index with 25 threads. Here is the query (random non-existent refKey each time)

{
  "query": {
    "bool": {
      "filter": [
        {
          "terms": {
            "refKey": [
              "431012698-1x"
            ]
          }
        },
        {
          "terms": {
            "country": [
              "Albania", "Malawi", "Ethiopia", "Germany", "Australia", "Jordan", "Lebanon", "Colombia", "Denmark", "Belarus",
              "Angola", "Egypt", "Ireland", "Cyprus", "Croatia", "Kuwait", "Vietnam", "Philippines",
              "Mexico", "Spain", "Ukraine", "Turkey", "Slovenia", "Russia", "Norway", "Mongolia"
            ]
          }
        }
      ]
    }
  }
}

This query doesn't match any documents, but more importantly it takes roughly 7 times longer in 8.11 compared to 7.13

Profile confirms this. In 7.13, the 'country' filter, which actually has matches, is short circuited

"type": "TermInSetQuery",
"description": "country:(Albania Angola Australia Belarus Colombia Croatia Cyprus Denmark Egypt Ethiopia Germany Ireland Jordan Kuwait Lebanon Malawi Mexico Mongolia Norway Philippines Russia Slovenia Spain Turkey Ukraine Vietnam)",
"time_in_nanos": 1700

where as it takes significantly longer in 8.11

"type": "MultiTermQueryConstantScoreBlendedWrapper",
"description": "country:(Albania Angola Australia Belarus Colombia Croatia Cyprus Denmark Egypt Ethiopia Germany Ireland Jordan Kuwait Lebanon Malawi Mexico Mongolia Norway Philippines Russia Slovenia Spain Turkey Ukraine Vietnam)",
"time_in_nanos": 14052600

This has caused major performance issues for us with the upgrade. Is this a known defect?

3 Likes

Elastic support advised to change the first terms query into a term query. The query now performs like it used to in 7.13, and it no longer spends anytime in advance and build_scorer phases of the second terms query.

However it still feels like a regression to me. What if I have to search for multiple ref keys. It still performs like a dog in that scenario. Also why can't elastic rewrite the terms query into a term query when the array has just one value.

May be open an issue with this example?

I was advised a fix is coming in Lucene to address this issue
MultiTermQuery return null for ScoreSupplier by mayya-sharipova · Pull Request #13454 · apache/lucene · GitHub

1 Like