@@ -566,6 +566,7 @@ private Response query(String query, String filterPath) throws IOException {
566
566
.setRequestConfig (RequestConfig .custom ().setSocketTimeout (Math .toIntExact (TimeValue .timeValueMinutes (6 ).millis ())).build ())
567
567
.setWarningsHandler (WarningsHandler .PERMISSIVE )
568
568
);
569
+ logger .info ("Running query:" + query );
569
570
return runQuery (() -> client ().performRequest (request ));
570
571
}
571
572
@@ -735,28 +736,48 @@ private Map<String, Object> fetchMvLongs() throws IOException {
735
736
public void testLookupExplosion () throws IOException {
736
737
int sensorDataCount = 400 ;
737
738
int lookupEntries = 10000 ;
738
- Map <?, ?> map = lookupExplosion (sensorDataCount , lookupEntries , 1 , lookupEntries );
739
+ Map <?, ?> map = lookupExplosion (sensorDataCount , lookupEntries , 1 , lookupEntries , false );
739
740
assertMap (map , matchesMap ().extraOk ().entry ("values" , List .of (List .of (sensorDataCount * lookupEntries ))));
740
741
}
741
742
742
743
public void testLookupExplosionManyFields () throws IOException {
743
744
int sensorDataCount = 400 ;
744
745
int lookupEntries = 1000 ;
745
746
int joinFieldsCount = 990 ;
746
- Map <?, ?> map = lookupExplosion (sensorDataCount , lookupEntries , joinFieldsCount , lookupEntries );
747
+ Map <?, ?> map = lookupExplosion (sensorDataCount , lookupEntries , joinFieldsCount , lookupEntries , false );
748
+ assertMap (map , matchesMap ().extraOk ().entry ("values" , List .of (List .of (sensorDataCount * lookupEntries ))));
749
+ }
750
+
751
+ public void testLookupExplosionExpression () throws IOException {
752
+ int sensorDataCount = 400 ;
753
+ int lookupEntries = 10000 ;
754
+ Map <?, ?> map = lookupExplosion (sensorDataCount , lookupEntries , 1 , lookupEntries , true );
755
+ assertMap (map , matchesMap ().extraOk ().entry ("values" , List .of (List .of (sensorDataCount * lookupEntries ))));
756
+ }
757
+
758
+ public void testLookupExplosionManyFieldsExpression () throws IOException {
759
+ int sensorDataCount = 400 ;
760
+ int lookupEntries = 1000 ;
761
+ int joinFieldsCount = 399 ;// only join on 399 columns due to max expression size of 400
762
+ Map <?, ?> map = lookupExplosion (sensorDataCount , lookupEntries , joinFieldsCount , lookupEntries , true );
747
763
assertMap (map , matchesMap ().extraOk ().entry ("values" , List .of (List .of (sensorDataCount * lookupEntries ))));
748
764
}
749
765
750
766
public void testLookupExplosionManyMatchesManyFields () throws IOException {
751
767
// 1500, 10000 is enough locally, but some CI machines need more.
752
768
int lookupEntries = 10000 ;
753
- assertCircuitBreaks (attempt -> lookupExplosion (attempt * 1500 , lookupEntries , 30 , lookupEntries ));
769
+ assertCircuitBreaks (attempt -> lookupExplosion (attempt * 1500 , lookupEntries , 30 , lookupEntries , false ));
754
770
}
755
771
756
772
public void testLookupExplosionManyMatches () throws IOException {
757
773
// 1500, 10000 is enough locally, but some CI machines need more.
758
774
int lookupEntries = 10000 ;
759
- assertCircuitBreaks (attempt -> lookupExplosion (attempt * 1500 , lookupEntries , 1 , lookupEntries ));
775
+ assertCircuitBreaks (attempt -> lookupExplosion (attempt * 1500 , lookupEntries , 1 , lookupEntries , false ));
776
+ }
777
+
778
+ public void testLookupExplosionManyMatchesExpression () throws IOException {
779
+ int lookupEntries = 10000 ;
780
+ assertCircuitBreaks (attempt -> lookupExplosion (attempt * 1500 , lookupEntries , 1 , lookupEntries , true ));
760
781
}
761
782
762
783
public void testLookupExplosionManyMatchesFiltered () throws IOException {
@@ -768,9 +789,21 @@ public void testLookupExplosionManyMatchesFiltered() throws IOException {
768
789
int reductionFactor = 1000 ; // reduce the number of matches by this factor
769
790
// lookupEntries % reductionFactor must be 0 to ensure the number of rows returned matches the expected value
770
791
assertTrue (0 == lookupEntries % reductionFactor );
771
- Map <?, ?> map = lookupExplosion (sensorDataCount , lookupEntries , 1 , lookupEntries / reductionFactor );
792
+ Map <?, ?> map = lookupExplosion (sensorDataCount , lookupEntries , 1 , lookupEntries / reductionFactor , false );
772
793
assertMap (map , matchesMap ().extraOk ().entry ("values" , List .of (List .of (sensorDataCount * lookupEntries / reductionFactor ))));
794
+ }
773
795
796
+ public void testLookupExplosionManyMatchesFilteredExpression () throws IOException {
797
+ // This test will only work with the expanding join optimization
798
+ // that pushes the filter to the right side of the lookup.
799
+ // Without the optimization, it will fail with circuit_breaking_exception
800
+ int sensorDataCount = 10000 ;
801
+ int lookupEntries = 10000 ;
802
+ int reductionFactor = 1000 ; // reduce the number of matches by this factor
803
+ // lookupEntries % reductionFactor must be 0 to ensure the number of rows returned matches the expected value
804
+ assertTrue (0 == lookupEntries % reductionFactor );
805
+ Map <?, ?> map = lookupExplosion (sensorDataCount , lookupEntries , 1 , lookupEntries / reductionFactor , true );
806
+ assertMap (map , matchesMap ().extraOk ().entry ("values" , List .of (List .of (sensorDataCount * lookupEntries / reductionFactor ))));
774
807
}
775
808
776
809
public void testLookupExplosionNoFetch () throws IOException {
@@ -797,17 +830,33 @@ public void testLookupExplosionBigStringManyMatches() throws IOException {
797
830
assertCircuitBreaks (attempt -> lookupExplosionBigString (attempt * 500 , 1 ));
798
831
}
799
832
800
- private Map <String , Object > lookupExplosion (int sensorDataCount , int lookupEntries , int joinFieldsCount , int lookupEntriesToKeep )
801
- throws IOException {
833
+ private Map <String , Object > lookupExplosion (
834
+ int sensorDataCount ,
835
+ int lookupEntries ,
836
+ int joinFieldsCount ,
837
+ int lookupEntriesToKeep ,
838
+ boolean expressionBasedJoin
839
+ ) throws IOException {
802
840
try {
803
- lookupExplosionData (sensorDataCount , lookupEntries , joinFieldsCount );
841
+ lookupExplosionData (sensorDataCount , lookupEntries , joinFieldsCount , expressionBasedJoin );
804
842
StringBuilder query = startQuery ();
805
843
query .append ("FROM sensor_data | LOOKUP JOIN sensor_lookup ON " );
806
- for (int i = 0 ; i < joinFieldsCount ; i ++) {
807
- if (i != 0 ) {
808
- query .append ("," );
844
+ if (expressionBasedJoin ) {
845
+ for (int i = 0 ; i < joinFieldsCount ; i ++) {
846
+ if (i != 0 ) {
847
+ query .append (" AND " );
848
+ }
849
+ query .append ("id_left" ).append (i );
850
+ query .append ("==" );
851
+ query .append ("id_right" ).append (i );
852
+ }
853
+ } else {
854
+ for (int i = 0 ; i < joinFieldsCount ; i ++) {
855
+ if (i != 0 ) {
856
+ query .append ("," );
857
+ }
858
+ query .append ("id" ).append (i );
809
859
}
810
- query .append ("id" ).append (i );
811
860
}
812
861
if (lookupEntries != lookupEntriesToKeep ) {
813
862
// add a filter to reduce the number of matches
@@ -826,7 +875,7 @@ private Map<String, Object> lookupExplosion(int sensorDataCount, int lookupEntri
826
875
827
876
private Map <String , Object > lookupExplosionNoFetch (int sensorDataCount , int lookupEntries ) throws IOException {
828
877
try {
829
- lookupExplosionData (sensorDataCount , lookupEntries , 1 );
878
+ lookupExplosionData (sensorDataCount , lookupEntries , 1 , false );
830
879
StringBuilder query = startQuery ();
831
880
query .append ("FROM sensor_data | LOOKUP JOIN sensor_lookup ON id0 | STATS COUNT(*)\" }" );
832
881
return responseAsMap (query (query .toString (), null ));
@@ -836,14 +885,15 @@ private Map<String, Object> lookupExplosionNoFetch(int sensorDataCount, int look
836
885
}
837
886
}
838
887
839
- private void lookupExplosionData (int sensorDataCount , int lookupEntries , int joinFieldCount ) throws IOException {
840
- initSensorData (sensorDataCount , 1 , joinFieldCount );
841
- initSensorLookup (lookupEntries , 1 , i -> "73.9857 40.7484" , joinFieldCount );
888
+ private void lookupExplosionData (int sensorDataCount , int lookupEntries , int joinFieldCount , boolean expressionBasedJoin )
889
+ throws IOException {
890
+ initSensorData (sensorDataCount , 1 , joinFieldCount , expressionBasedJoin );
891
+ initSensorLookup (lookupEntries , 1 , i -> "73.9857 40.7484" , joinFieldCount , expressionBasedJoin );
842
892
}
843
893
844
894
private Map <String , Object > lookupExplosionBigString (int sensorDataCount , int lookupEntries ) throws IOException {
845
895
try {
846
- initSensorData (sensorDataCount , 1 , 1 );
896
+ initSensorData (sensorDataCount , 1 , 1 , false );
847
897
initSensorLookupString (lookupEntries , 1 , i -> {
848
898
int target = Math .toIntExact (ByteSizeValue .ofMb (1 ).getBytes ());
849
899
StringBuilder str = new StringBuilder (Math .toIntExact (ByteSizeValue .ofMb (2 ).getBytes ()));
@@ -876,7 +926,7 @@ public void testEnrichExplosionManyMatches() throws IOException {
876
926
877
927
private Map <String , Object > enrichExplosion (int sensorDataCount , int lookupEntries ) throws IOException {
878
928
try {
879
- initSensorData (sensorDataCount , 1 , 1 );
929
+ initSensorData (sensorDataCount , 1 , 1 , false );
880
930
initSensorEnrich (lookupEntries , 1 , i -> "73.9857 40.7484" );
881
931
try {
882
932
StringBuilder query = startQuery ();
@@ -1050,7 +1100,7 @@ private void initMvLongsIndex(int docs, int fields, int fieldValues) throws IOEx
1050
1100
initIndex ("mv_longs" , bulk .toString ());
1051
1101
}
1052
1102
1053
- private void initSensorData (int docCount , int sensorCount , int joinFieldCount ) throws IOException {
1103
+ private void initSensorData (int docCount , int sensorCount , int joinFieldCount , boolean expressionBasedJoin ) throws IOException {
1054
1104
logger .info ("loading sensor data" );
1055
1105
// We cannot go over 1000 fields, due to failed on parsing mappings on index creation
1056
1106
// [sensor_data] java.lang.IllegalArgumentException: Limit of total fields [1000] has been exceeded
@@ -1061,8 +1111,9 @@ private void initSensorData(int docCount, int sensorCount, int joinFieldCount) t
1061
1111
"properties": {
1062
1112
"@timestamp": { "type": "date" },
1063
1113
""" );
1114
+ String suffix = expressionBasedJoin ? "_left" : "" ;
1064
1115
for (int i = 0 ; i < joinFieldCount ; i ++) {
1065
- createIndexBuilder .append ("\" id" ).append (i ).append ("\" : { \" type\" : \" long\" }," );
1116
+ createIndexBuilder .append ("\" id" ).append (suffix ). append ( i ).append ("\" : { \" type\" : \" long\" }," );
1066
1117
}
1067
1118
createIndexBuilder .append ("""
1068
1119
"value": { "type": "double" }
@@ -1083,7 +1134,7 @@ private void initSensorData(int docCount, int sensorCount, int joinFieldCount) t
1083
1134
{"create":{}}
1084
1135
{"timestamp":"%s",""" , DateFieldMapper .DEFAULT_DATE_TIME_FORMATTER .formatMillis (i * 10L + firstDate )));
1085
1136
for (int j = 0 ; j < joinFieldCount ; j ++) {
1086
- data .append (String .format (Locale .ROOT , "\" id%d\" :%d, " , j , i % sensorCount ));
1137
+ data .append (String .format (Locale .ROOT , "\" id%s% d\" :%d, " , suffix , j , i % sensorCount ));
1087
1138
}
1088
1139
data .append (String .format (Locale .ROOT , "\" value\" : %f}\n " , i * 1.1 ));
1089
1140
if (i % docsPerBulk == docsPerBulk - 1 ) {
@@ -1094,8 +1145,13 @@ private void initSensorData(int docCount, int sensorCount, int joinFieldCount) t
1094
1145
initIndex ("sensor_data" , data .toString ());
1095
1146
}
1096
1147
1097
- private void initSensorLookup (int lookupEntries , int sensorCount , IntFunction <String > location , int joinFieldsCount )
1098
- throws IOException {
1148
+ private void initSensorLookup (
1149
+ int lookupEntries ,
1150
+ int sensorCount ,
1151
+ IntFunction <String > location ,
1152
+ int joinFieldsCount ,
1153
+ boolean expressionBasedJoin
1154
+ ) throws IOException {
1099
1155
logger .info ("loading sensor lookup" );
1100
1156
// cannot go over 1000 fields, due to failed on parsing mappings on index creation
1101
1157
// [sensor_data] java.lang.IllegalArgumentException: Limit of total fields [1000] has been exceeded
@@ -1105,8 +1161,9 @@ private void initSensorLookup(int lookupEntries, int sensorCount, IntFunction<St
1105
1161
{
1106
1162
"properties": {
1107
1163
""" );
1164
+ String suffix = expressionBasedJoin ? "_right" : "" ;
1108
1165
for (int i = 0 ; i < joinFieldsCount ; i ++) {
1109
- createIndexBuilder .append ("\" id" ).append (i ).append ("\" : { \" type\" : \" long\" }," );
1166
+ createIndexBuilder .append ("\" id" ).append (suffix ). append ( i ).append ("\" : { \" type\" : \" long\" }," );
1110
1167
}
1111
1168
createIndexBuilder .append ("""
1112
1169
"location": { "type": "geo_point" },
@@ -1127,7 +1184,7 @@ private void initSensorLookup(int lookupEntries, int sensorCount, IntFunction<St
1127
1184
{"create":{}}
1128
1185
{""" ));
1129
1186
for (int j = 0 ; j < joinFieldsCount ; j ++) {
1130
- data .append (String .format (Locale .ROOT , "\" id%d\" :%d, " , j , sensor ));
1187
+ data .append (String .format (Locale .ROOT , "\" id%s% d\" :%d, " , suffix , j , sensor ));
1131
1188
}
1132
1189
data .append (String .format (Locale .ROOT , """
1133
1190
"location": "POINT(%s)", "filter_key": %d}\n """ , location .apply (sensor ), i ));
@@ -1165,7 +1222,7 @@ private void initSensorLookupString(int lookupEntries, int sensorCount, IntFunct
1165
1222
}
1166
1223
1167
1224
private void initSensorEnrich (int lookupEntries , int sensorCount , IntFunction <String > location ) throws IOException {
1168
- initSensorLookup (lookupEntries , sensorCount , location , 1 );
1225
+ initSensorLookup (lookupEntries , sensorCount , location , 1 , false );
1169
1226
logger .info ("loading sensor enrich" );
1170
1227
1171
1228
Request create = new Request ("PUT" , "/_enrich/policy/sensor" );
0 commit comments