-
Notifications
You must be signed in to change notification settings - Fork 25.5k
ES|QL: Score all docs in a single getOutput call in LuceneTopNSourceOperator #136172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ES|QL: Score all docs in a single getOutput call in LuceneTopNSourceOperator #136172
Conversation
Pinging @elastic/es-search-relevance (Team:Search Relevance) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good to me. One question before merging - could this run for, like, minutes? I imagine in some rare cases with runtime fields and no timestamp query it's possible, though unlikely. But in other cases. Like, in anything approximating a "normal" case?
I ask because we don't have a thing that updates the driver status
outside of the main loop. So if this run "forever" then we won't see it in the status. I don't think this is a problem here, but it might be worth a comment.
Mostly I'm having flashbacks to that time when I made an agg run for a week.
|
||
// If we stayed longer than 1 second to execute getOutput, we should return back to the driver, so we can update its status. | ||
// Even if this should almost never happen, we want to update the driver status even when a query runs "forever". | ||
if (TimeUnit.SECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS) >= 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd yank this into a constant - maybe even one in nanos. Just a little more expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep - makes sense - guess I was in too much of a hurry - addressed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not too much a of hurry, just a little thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks @ioanatia
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great.
The
LuceneTopNOperator
cannot output pages until it collects the top N docs, by scoring all potential matches.LuceneTopNOperator
scores documents in batches - a single call ofrunSingleLoopIteration
fromDriver
corresponds to scoring a single batch of documents inLuceneTopNOperator
withscorer.scoreNextRange(...
.In
runSingleLoopIteration
we iterate through all the operators if they have a page to output so we can feed it to the next operator. This method is called in a loop inDriver#run
. We do a lot of extra computation forLuceneTopNOperator
to start emitting pages.What we'd want is to not require multiple calls to
LuceneTopNOperator#getOutput
to actually output pages, and to be able to emit a page from the first time we call this method.However we still want to make sure we don't block the execution such that the query cannot be cancelled while
LuceneTopNOperator#getOutput
runs.To mitigate this, we pass the
DriverContext
to theLuceneTopNOperator
such that we can check if the query has been cancelled withdriverContext.checkForEarlyTermination()
.We can do a similar optimization for
LuceneCountOperator
if we are happy with this one.