Skip to content
6 changes: 6 additions & 0 deletions docs/changelog/132889.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 132889
summary: Improve Expanding Lookup Join performance by pushing a filter to the lookup
join
area: "ES|QL"
type: enhancement
issues: [ ]
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ static TransportVersion def(int id) {
public static final TransportVersion SIMULATE_INGEST_MAPPING_MERGE_TYPE = def(9_138_0_00);
public static final TransportVersion ESQL_LOOKUP_JOIN_ON_MANY_FIELDS = def(9_139_0_00);
public static final TransportVersion SIMULATE_INGEST_EFFECTIVE_MAPPING = def(9_140_0_00);
public static final TransportVersion ESQL_LOOKUP_JOIN_PRE_JOIN_FILTER = def(9_141_0_00);

/*
* STOP! READ THIS FIRST! No, really,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ Page buildPage(int positions, IntVector.Builder positionsBuilder, IntVector.Buil
return page;
}

private Query nextQuery() {
private Query nextQuery() throws IOException {
++queryPosition;
while (isFinished() == false) {
Query query = queryList.getQuery(queryPosition);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.apache.lucene.search.Query;
import org.elasticsearch.core.Nullable;

import java.io.IOException;

/**
* An interface to generates queries for the lookup and enrich operators.
* This interface is used to retrieve queries based on a position index.
Expand All @@ -20,7 +22,7 @@ public interface LookupEnrichQueryGenerator {
* Returns the query at the given position.
*/
@Nullable
Query getQuery(int position);
Query getQuery(int position) throws IOException;

/**
* Returns the number of queries in this generator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5149,3 +5149,200 @@ null | null | bar2 | null | null
null | null | corge | null | null
null | null | fred | null | null
;


lookupJoinWithPushableFilterOnLeft
required_capability: join_lookup_v12
required_capability: lookup_join_on_multiple_fields

FROM multi_column_joinable
| LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool
| WHERE other2 > 5000
| KEEP id_int, name_str, extra1, other1, other2
| SORT id_int, name_str, extra1, other1, other2
| LIMIT 20
;

warning:Line 2:3: evaluation of [LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool] failed, treating result as null. Only first 20 failures recorded.
warning:Line 2:3: java.lang.IllegalArgumentException: LOOKUP JOIN encountered multi-value

id_int:integer | name_str:keyword | extra1:keyword | other1:keyword | other2:integer
4 | David | qux | zeta | 6000
5 | Eve | quux | eta | 7000
5 | Eve | quux | theta | 8000
6 | null | corge | iota | 9000
7 | Grace | grault | kappa | 10000
8 | Hank | garply | lambda | 11000
12 | Liam | xyzzy | nu | 13000
13 | Mia | thud | xi | 14000
14 | Nina | foo2 | omicron | 15000
;

lookupJoinWithTwoPushableFiltersOnLeft
required_capability: join_lookup_v12
required_capability: lookup_join_on_multiple_fields

FROM multi_column_joinable
| LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool
| WHERE other2 > 5000
| WHERE other1 like "*ta"
| KEEP id_int, name_str, extra1, other1, other2
| SORT id_int, name_str, extra1, other1, other2
| LIMIT 20
;

warning:Line 2:3: evaluation of [LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool] failed, treating result as null. Only first 20 failures recorded.
warning:Line 2:3: java.lang.IllegalArgumentException: LOOKUP JOIN encountered multi-value

id_int:integer | name_str:keyword | extra1:keyword | other1:keyword | other2:integer
4 | David | qux | zeta | 6000
5 | Eve | quux | eta | 7000
5 | Eve | quux | theta | 8000
6 | null | corge | iota | 9000
;

lookupJoinWithMixLeftAndRightFilters
required_capability: join_lookup_v12
required_capability: lookup_join_on_multiple_fields

FROM multi_column_joinable
| LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool
| WHERE other2 > 5000 AND (extra1 == "qux" OR extra1 == "foo2") AND other1 like ("*ta", "*ron")
| KEEP id_int, name_str, extra1, other1, other2
| SORT id_int, name_str, extra1, other1, other2
| LIMIT 20
;

id_int:integer | name_str:keyword | extra1:keyword | other1:keyword | other2:integer
4 | David | qux | zeta | 6000
14 | Nina | foo2 | omicron | 15000
;

lookupJoinWithMixLeftAndRightFiltersNotPushableToLucene
required_capability: join_lookup_v12
required_capability: lookup_join_on_multiple_fields

FROM multi_column_joinable
| LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool
| WHERE ABS(other2) > 5000 AND (extra1 == "qux" OR extra1 == "foo2") AND other1 like ("*ta", "*ron")
| KEEP id_int, name_str, extra1, other1, other2
| SORT id_int, name_str, extra1, other1, other2
| LIMIT 20
;

id_int:integer | name_str:keyword | extra1:keyword | other1:keyword | other2:integer
4 | David | qux | zeta | 6000
14 | Nina | foo2 | omicron | 15000
;


lookupJoinWithMixJoinAndNonJoinColumnsNotPushable
required_capability: join_lookup_v12
required_capability: lookup_join_on_multiple_fields

FROM multi_column_joinable
| LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool
| WHERE ABS(other2) > id_int + 5000
| KEEP id_int, name_str, extra1, other1, other2
| SORT id_int, name_str, extra1, other1, other2
| LIMIT 20
;

warning:Line 2:3: evaluation of [LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool] failed, treating result as null. Only first 20 failures recorded.
warning:Line 2:3: java.lang.IllegalArgumentException: LOOKUP JOIN encountered multi-value
warning:Line 3:23: evaluation of [id_int + 5000] failed, treating result as null. Only first 20 failures recorded.
warning:Line 3:23: java.lang.IllegalArgumentException: single-value function encountered multi-value

id_int:integer | name_str:keyword | extra1:keyword | other1:keyword | other2:integer
4 | David | qux | zeta | 6000
5 | Eve | quux | eta | 7000
5 | Eve | quux | theta | 8000
6 | null | corge | iota | 9000
7 | Grace | grault | kappa | 10000
8 | Hank | garply | lambda | 11000
12 | Liam | xyzzy | nu | 13000
13 | Mia | thud | xi | 14000
14 | Nina | foo2 | omicron | 15000
;


lookupJoinWithMixJoinAndNonJoinColumnsPushable
required_capability: join_lookup_v12
required_capability: lookup_join_on_multiple_fields

FROM multi_column_joinable
| LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool
| WHERE other2 > id_int + 5000
| KEEP id_int, name_str, extra1, other1, other2
| SORT id_int, name_str, extra1, other1, other2
| LIMIT 20
;

warning:Line 2:3: evaluation of [LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool] failed, treating result as null. Only first 20 failures recorded.
warning:Line 2:3: java.lang.IllegalArgumentException: LOOKUP JOIN encountered multi-value
warning:Line 3:18: evaluation of [id_int + 5000] failed, treating result as null. Only first 20 failures recorded.
warning:Line 3:18: java.lang.IllegalArgumentException: single-value function encountered multi-value

id_int:integer | name_str:keyword | extra1:keyword | other1:keyword | other2:integer
4 | David | qux | zeta | 6000
5 | Eve | quux | eta | 7000
5 | Eve | quux | theta | 8000
6 | null | corge | iota | 9000
7 | Grace | grault | kappa | 10000
8 | Hank | garply | lambda | 11000
12 | Liam | xyzzy | nu | 13000
13 | Mia | thud | xi | 14000
14 | Nina | foo2 | omicron | 15000
;

lookupJoinWithJoinAttrFilter
required_capability: join_lookup_v12
required_capability: lookup_join_on_multiple_fields

FROM multi_column_joinable
| LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool
| WHERE id_int > 7
| KEEP id_int, name_str, extra1, other1, other2
| SORT id_int, name_str, extra1, other1, other2
| LIMIT 20
;

warning:Line 3:9: evaluation of [id_int > 7] failed, treating result as null. Only first 20 failures recorded.
warning:Line 3:9: java.lang.IllegalArgumentException: single-value function encountered multi-value

id_int:integer | name_str:keyword | extra1:keyword | other1:keyword | other2:integer
8 | Hank | garply | lambda | 11000
9 | null | waldo | null | null
10 | null | fred | null | null
12 | Liam | xyzzy | nu | 13000
13 | Mia | thud | xi | 14000
14 | Nina | foo2 | omicron | 15000
15 | null | bar2 | null | null
;


lookupJoinWithExpressionOfOtherFields
required_capability: join_lookup_v12
required_capability: lookup_join_on_multiple_fields

FROM multi_column_joinable
| LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool
| WHERE ABS(other2) > LENGTH(other1)*1000 + 2000
| KEEP id_int, name_str, extra1, other1, other2
| SORT id_int, name_str, extra1, other1, other2
| LIMIT 20
;

warning:Line 2:3: evaluation of [LOOKUP JOIN multi_column_joinable_lookup ON id_int, is_active_bool] failed, treating result as null. Only first 20 failures recorded.
warning:Line 2:3: java.lang.IllegalArgumentException: LOOKUP JOIN encountered multi-value

id_int:integer | name_str:keyword | extra1:keyword | other1:keyword | other2:integer
5 | Eve | quux | eta | 7000
5 | Eve | quux | theta | 8000
6 | null | corge | iota | 9000
7 | Grace | grault | kappa | 10000
8 | Hank | garply | lambda | 11000
12 | Liam | xyzzy | nu | 13000
13 | Mia | thud | xi | 14000
14 | Nina | foo2 | omicron | 15000
;
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ private void runLookup(List<DataType> keyTypes, PopulateIndices populateIndices)
"lookup",
"lookup",
List.of(new Alias(Source.EMPTY, "l", new ReferenceAttribute(Source.EMPTY, "l", DataType.LONG))),
Source.EMPTY
Source.EMPTY,
null
);
DriverContext driverContext = driverContext();
try (
Expand Down
Loading