Skip to content

Commit b389762

Browse files
committed
very good results with few regressions
1 parent 3d8f152 commit b389762

4 files changed

Lines changed: 322 additions & 29 deletions

File tree

core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/optimizer/QueryJoinOptimizer.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -726,9 +726,10 @@ private boolean isUnsafeCoreInEqualityValue(Value value) {
726726
return false;
727727
}
728728
CoreDatatype coreDatatype = ((Literal) value).getCoreDatatype();
729-
if(coreDatatype.isXSDDatatype()){
729+
if (coreDatatype.isXSDDatatype()) {
730730
CoreDatatype.XSD xsdDatatype = coreDatatype.asXSDDatatypeOrNull();
731-
return xsdDatatype.isNumericDatatype() || xsdDatatype.isCalendarDatatype() || xsdDatatype == CoreDatatype.XSD.BOOLEAN;
731+
return xsdDatatype.isNumericDatatype() || xsdDatatype.isCalendarDatatype()
732+
|| xsdDatatype == CoreDatatype.XSD.BOOLEAN;
732733
}
733734
return false;
734735
}
@@ -1320,7 +1321,7 @@ private Deque<TupleExpr> optimizeJoinGroup(List<TupleExpr> joinGroup, List<Defer
13201321
boundVars.addAll(tupleExpr.getBindingNames());
13211322
}
13221323

1323-
if (REORDER_JOINS_WITH_SKETCHES && orderedJoinArgs.size() > 2
1324+
if (REORDER_JOINS_WITH_SKETCHES && orderedJoinArgs.size() >= 2
13241325
&& (statistics.supportsJoinEstimation()
13251326
|| (!deferredFilters.isEmpty() && statistics.supportsFilterSelectivityCosting()))) {
13261327
orderedJoinArgs = new ArrayDeque<>(

core/sail/base/src/main/java/org/eclipse/rdf4j/sail/base/SketchJoinOrderPlanner.java

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ final class SketchJoinOrderPlanner {
5252
private static final double SMALL_BINDING_SET_ASSIGNMENT_SCORE_RATIO = 0.05d;
5353
private static final double BOUND_TYPE_GUARD_DELAY_PENALTY = 4.0d;
5454
private static final double PENDING_SMALL_VALUES_ANCHOR_FILTER_PENALTY = 4.0d;
55+
private static final double PENDING_TYPE_GUARD_BROAD_SCAN_RATIO = 4.0d;
5556
private static final double BROAD_EDGE_PENDING_CONSTRAINT_PENALTY = 4.0d;
5657
private static final double MAX_BROAD_EDGE_PENDING_CONSTRAINT_PENALTY = 1024.0d;
5758
private static final double BROAD_EDGE_MIN_ROWS = 1024.0d;
@@ -1170,9 +1171,7 @@ private double adjustedWorkRows(SketchBasedJoinEstimator.AccessShape accessShape
11701171
if (!(Double.isFinite(adjustedWorkRows) && adjustedWorkRows > 0.0d)) {
11711172
return defaultWorkRows;
11721173
}
1173-
return Double.isFinite(defaultWorkRows) && defaultWorkRows >= 0.0d
1174-
? Math.min(adjustedWorkRows, defaultWorkRows)
1175-
: adjustedWorkRows;
1174+
return adjustedWorkRows;
11761175
}
11771176

11781177
private double adjustedTransitionWorkRows(int factorIndex, long mask, long currentlyBoundVarMask,
@@ -1210,20 +1209,13 @@ private double repeatedLookupWorkRows(SketchBasedJoinEstimator.TuplePlanEstimate
12101209
}
12111210

12121211
private double applyUnlockedFilterWorkRows(long previousMask, long nextMask, double workRows) {
1213-
double passRatio = newlyUnlockedFilterPassRatio(previousMask, nextMask);
1214-
if (passRatio >= 1.0d) {
1215-
return workRows;
1216-
}
1217-
double filteredWorkRows = workRows * passRatio;
1218-
if (!Double.isFinite(filteredWorkRows) || filteredWorkRows < 0.0d) {
1219-
return workRows;
1220-
}
1221-
return filteredWorkRows;
1212+
return workRows;
12221213
}
12231214

12241215
private double orderingScoreRows(int factorIndex, long previousMask, long nextMask, double workRows,
12251216
double outputRows, double prefixRows) {
1226-
double scoreRows = workRows * newlyUnlockedFilterScoreRatio(previousMask, nextMask);
1217+
double unlockedFilterScoreRatio = newlyUnlockedFilterScoreRatio(previousMask, nextMask);
1218+
double scoreRows = workRows * unlockedFilterScoreRatio;
12271219
if (!Double.isFinite(scoreRows) || scoreRows < 0.0d) {
12281220
scoreRows = workRows;
12291221
}
@@ -1233,9 +1225,11 @@ private double orderingScoreRows(int factorIndex, long previousMask, long nextMa
12331225
scoreRows *= pendingConstraintPenalty;
12341226
}
12351227
double localFilterMultiplier = selectiveLocalFilterMultiplier(factorIndex);
1228+
boolean hasSelectiveFilterScore = unlockedFilterScoreRatio < 1.0d;
12361229
if (localFilterMultiplier < 1.0d && Double.isFinite(outputRows) && outputRows >= 0.0d) {
12371230
scoreRows = Math.min(scoreRows, outputRows);
12381231
scoreRows *= Math.max(localFilterMultiplier, CHEAP_UNLOCKED_FILTER_SCORE_RATIO);
1232+
hasSelectiveFilterScore = true;
12391233
}
12401234
scoreRows *= pendingCheapFilterUnlockBeforeBroadEdgePenalty(previousMask, factorIndex);
12411235
if (hasSelectiveLocalFilter(factorIndex) && hasPendingSmallValuesAnchoredSibling(previousMask, factorIndex)) {
@@ -1244,6 +1238,14 @@ private double orderingScoreRows(int factorIndex, long previousMask, long nextMa
12441238
if (hasSelectiveLocalFilter(factorIndex) && hasValuesAnchoredStructuralBridge(previousMask, factorIndex)) {
12451239
scoreRows *= PENDING_SMALL_VALUES_ANCHOR_FILTER_PENALTY;
12461240
}
1241+
if (previousMask == 0L && hasSelectiveFilterScore) {
1242+
double typeGuardScoreRows = pendingSmallSameSubjectRdfTypeGuardScoreRows(factorIndex);
1243+
if (Double.isFinite(typeGuardScoreRows) && typeGuardScoreRows >= 0.0d
1244+
&& Double.isFinite(workRows)
1245+
&& typeGuardScoreRows * PENDING_TYPE_GUARD_BROAD_SCAN_RATIO < workRows) {
1246+
scoreRows = Math.max(scoreRows, Math.nextUp(typeGuardScoreRows));
1247+
}
1248+
}
12471249
double reachableSelectiveFilterRatio = newlyReachableSelectiveLocalFilterRatio(previousMask, nextMask);
12481250
if (reachableSelectiveFilterRatio < 1.0d) {
12491251
scoreRows *= reachableSelectiveFilterRatio;
@@ -1263,6 +1265,55 @@ private double orderingScoreRows(int factorIndex, long previousMask, long nextMa
12631265
return scoreRows;
12641266
}
12651267

1268+
private double pendingSmallSameSubjectRdfTypeGuardScoreRows(int factorIndex) {
1269+
StatementPattern statementPattern = statementPattern(factors.get(factorIndex).tupleExpr());
1270+
if (statementPattern == null || hasConstantValue(statementPattern.getPredicateVar(), RDF_TYPE_IRI)) {
1271+
return Double.NaN;
1272+
}
1273+
Var subjectVar = statementPattern.getSubjectVar();
1274+
if (subjectVar == null || subjectVar.hasValue() || subjectVar.getName() == null) {
1275+
return Double.NaN;
1276+
}
1277+
1278+
String subjectName = subjectVar.getName();
1279+
double bestScoreRows = Double.POSITIVE_INFINITY;
1280+
for (int i = 0; i < factors.size(); i++) {
1281+
if (i == factorIndex) {
1282+
continue;
1283+
}
1284+
double scoreRows = smallSameSubjectRdfTypeGuardScoreRows(i, subjectName);
1285+
if (Double.isFinite(scoreRows) && scoreRows >= 0.0d && scoreRows < bestScoreRows) {
1286+
bestScoreRows = scoreRows;
1287+
}
1288+
}
1289+
return bestScoreRows < Double.POSITIVE_INFINITY ? bestScoreRows : Double.NaN;
1290+
}
1291+
1292+
private double smallSameSubjectRdfTypeGuardScoreRows(int factorIndex, String subjectName) {
1293+
PlanFactor factor = factors.get(factorIndex);
1294+
StatementPattern statementPattern = statementPattern(factor.tupleExpr());
1295+
if (statementPattern == null || !hasConstantValue(statementPattern.getPredicateVar(), RDF_TYPE_IRI)) {
1296+
return Double.NaN;
1297+
}
1298+
Var subjectVar = statementPattern.getSubjectVar();
1299+
if (subjectVar == null || subjectVar.hasValue() || !subjectName.equals(subjectVar.getName())
1300+
|| statementPattern.getObjectVar() == null || !statementPattern.getObjectVar().hasValue()) {
1301+
return Double.NaN;
1302+
}
1303+
if (!hasOnlySubjectPlannerJoinVar(factor, subjectName)) {
1304+
return Double.NaN;
1305+
}
1306+
double outputRows = factor.estimate().outputRows();
1307+
if (!(Double.isFinite(outputRows) && outputRows >= 0.0d && outputRows <= BROAD_EDGE_MIN_ROWS)) {
1308+
return Double.NaN;
1309+
}
1310+
double adjustedWorkRows = adjustedWorkRows(factorIndex, 0L, initiallyBoundVarMask, outputRows);
1311+
if (!Double.isFinite(adjustedWorkRows) || adjustedWorkRows < 0.0d) {
1312+
return outputRows;
1313+
}
1314+
return Math.max(outputRows, adjustedWorkRows);
1315+
}
1316+
12661317
private double boundTypeGuardDelayPenalty(long previousMask, int factorIndex) {
12671318
if (previousMask == 0L || contains(previousMask, factorIndex)
12681319
|| !maskHasSelectiveLocalFilter(previousMask)
@@ -1284,19 +1335,31 @@ private double boundTypeGuardDelayPenalty(long previousMask, int factorIndex) {
12841335

12851336
private boolean isBoundRdfTypeGuard(long previousMask, int factorIndex) {
12861337
PlanFactor factor = factors.get(factorIndex);
1287-
if (factor.joinVars().size() != 1) {
1288-
return false;
1289-
}
12901338
StatementPattern statementPattern = statementPattern(factor.tupleExpr());
12911339
if (statementPattern == null || !hasConstantValue(statementPattern.getPredicateVar(), RDF_TYPE_IRI)) {
12921340
return false;
12931341
}
12941342
Var subjectVar = statementPattern.getSubjectVar();
12951343
return subjectVar != null && subjectVar.getName() != null
1344+
&& hasOnlySubjectPlannerJoinVar(factor, subjectVar.getName())
12961345
&& containsVariable(variablesMask(previousMask), subjectVar.getName())
12971346
&& statementPattern.getObjectVar() != null && statementPattern.getObjectVar().hasValue();
12981347
}
12991348

1349+
private static boolean hasOnlySubjectPlannerJoinVar(PlanFactor factor, String subjectName) {
1350+
boolean hasSubject = false;
1351+
for (String joinVar : factor.joinVars()) {
1352+
if (!isPlannerVariableName(joinVar)) {
1353+
continue;
1354+
}
1355+
if (!subjectName.equals(joinVar)) {
1356+
return false;
1357+
}
1358+
hasSubject = true;
1359+
}
1360+
return hasSubject;
1361+
}
1362+
13001363
private boolean introducesJoinVariable(long previousMask, int factorIndex) {
13011364
long previousVariables = variablesMask(previousMask);
13021365
return (joinVarMasks[factorIndex] & ~previousVariables) != 0L;

0 commit comments

Comments
 (0)