Skip to content

Commit 5eb2da9

Browse files
committed
another big updatw
1 parent 1fad651 commit 5eb2da9

25 files changed

Lines changed: 3341 additions & 97 deletions

core/query/src/main/java/org/eclipse/rdf4j/query/explanation/TelemetryMetricNames.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ private TelemetryMetricNames() {
115115
public static final String PLANNED_LOOKUP_COMPONENTS = "plannedLookupComponents";
116116
public static final String PLANNED_BOUND_VARS = "plannedBoundVars";
117117
public static final String PLANNED_WORK_ROWS = "plannedWorkRows";
118+
public static final String PLANNED_ACCESS_WORK_ROWS = "plannedAccessWorkRows";
118119
public static final String PLANNED_FILTER_PASS_RATIO = "plannedFilterPassRatio";
119120
public static final String PLANNED_FILTER_EVIDENCE_COUNT = "plannedFilterEvidenceCount";
120121
public static final String PLANNED_FILTER_CONFIDENCE = "plannedFilterConfidence";

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import java.util.function.Consumer;
5050

5151
import org.apache.datasketches.hash.MurmurHash3;
52+
import org.apache.datasketches.tuple.arrayofdoubles.ArrayOfDoublesCompactSketch;
5253
import org.apache.datasketches.tuple.arrayofdoubles.ArrayOfDoublesSketch;
5354
import org.apache.datasketches.tuple.arrayofdoubles.ArrayOfDoublesUpdatableSketch;
5455
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
@@ -2835,6 +2836,12 @@ private PatternStats freezePatternStats(PatternStats patternStats) {
28352836
if (patternStats.sketch == null) {
28362837
return patternStats;
28372838
}
2839+
if (patternStats.sketch.isEmpty()) {
2840+
return new PatternStats(EMPTY, patternStats.card);
2841+
}
2842+
if (patternStats.sketch instanceof ArrayOfDoublesCompactSketch) {
2843+
return patternStats;
2844+
}
28382845
return new PatternStats(patternStats.sketch.compact(), patternStats.card);
28392846
}
28402847

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

Lines changed: 259 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ final class SketchJoinOrderPlanner {
7171
private static final double FILTERED_SEED_MAX_STEP_WORK_RATIO = 12.0d;
7272
private static final double SEED_FILTER_ROW_FLOW_MAX_PASS_RATIO = 0.25d;
7373
private static final double BROAD_BRIDGE_ENDPOINT_PREP_MIN_RATIO = 3.0d;
74+
private static final double FINITE_DOMAIN_PREFIX_GUARD_MIN_ACCESS_ROWS = 1_000.0d;
7475
private static final int FINITE_DOMAIN_FILTER_MAX_ENUMERATED_BINDINGS = 4096;
7576
private static final int COMPLETED_DEFERRED_FILTER_CONNECTIONS = 2;
7677
private static final double DEFERRED_FILTER_ORDERING_MAX_PASS_RATIO = 0.5d;
@@ -874,6 +875,12 @@ private StatePlan seedPlan(int factorIndex) {
874875
if (!isFactorActionLegal(factorIndex, initiallyBoundVarMask)) {
875876
return null;
876877
}
878+
if (shouldDelayUnfilteredFiniteSeed(factorIndex)) {
879+
return null;
880+
}
881+
if (shouldDelayFiniteLookupGuardedSeed(factorIndex)) {
882+
return null;
883+
}
877884
long seedMask = bit(factorIndex);
878885
PlanFactor factor = factors.get(factorIndex);
879886
SketchBasedJoinEstimator.TuplePlanEstimate conditionedEstimate = conditionedFactorEstimate(factorIndex,
@@ -956,6 +963,63 @@ private StatePlan seedPlan(int factorIndex) {
956963
return applyAutomaticFilterActions(seed);
957964
}
958965

966+
private boolean shouldDelayUnfilteredFiniteSeed(int factorIndex) {
967+
if (!isSmallBindingSetAssignment(factorIndex)) {
968+
return false;
969+
}
970+
long seedVars = bindingVarMasks[factorIndex] & variableUniverseMask;
971+
if (finiteFilterParticipationCount(seedVars) > 0) {
972+
return false;
973+
}
974+
long assignments = smallBindingSetAssignmentFactorMask & ~bit(factorIndex);
975+
while (assignments != 0L) {
976+
int assignment = Long.numberOfTrailingZeros(assignments);
977+
assignments &= assignments - 1L;
978+
if (finiteFilterParticipationCount(bindingVarMasks[assignment] & variableUniverseMask) > 0) {
979+
return true;
980+
}
981+
}
982+
return false;
983+
}
984+
985+
private boolean shouldDelayFiniteLookupGuardedSeed(int factorIndex) {
986+
if (isBindingSetAssignment(factorIndex) || statementPatternFactor(factorIndex) == null) {
987+
return false;
988+
}
989+
long pendingAssignments = smallBindingSetAssignmentFactorMask;
990+
if (pendingAssignments == 0L) {
991+
return false;
992+
}
993+
long legalAssignments = 0L;
994+
long assignments = pendingAssignments;
995+
while (assignments != 0L) {
996+
int assignment = Long.numberOfTrailingZeros(assignments);
997+
assignments &= assignments - 1L;
998+
if (isFactorActionLegal(assignment, initiallyBoundVarMask)) {
999+
legalAssignments |= bit(assignment);
1000+
}
1001+
}
1002+
if (legalAssignments == 0L) {
1003+
return false;
1004+
}
1005+
long pendingAssignmentVars = assignmentVariableMask(legalAssignments) & ~initiallyBoundVarMask;
1006+
if (pendingAssignmentVars == 0L) {
1007+
return false;
1008+
}
1009+
SketchBasedJoinEstimator.TuplePlanEstimate conditionedEstimate = conditionedFactorEstimate(factorIndex,
1010+
initiallyBoundVarMask);
1011+
FactorPhysicalEstimate physicalEstimate = factorPhysicalEstimate(factorIndex, 0L, initiallyBoundVarMask,
1012+
conditionedEstimate.outputRows(), null);
1013+
if (isExactStatementDirectLookup(physicalEstimate)) {
1014+
return false;
1015+
}
1016+
long missingLookupVars = missingExactLookupVariableMask(factorIndex,
1017+
physicalEstimate.lookupComponentMask(), initiallyBoundVarMask);
1018+
return (missingLookupVars != 0L && (missingLookupVars & ~pendingAssignmentVars) == 0L)
1019+
|| shouldDelayBroadLookupForFinitePrefixGuard(physicalEstimate, missingLookupVars,
1020+
pendingAssignmentVars);
1021+
}
1022+
9591023
private boolean appliesSelectiveSeedFilterRowFlow(long seedMask,
9601024
SketchBasedJoinEstimator.TuplePlanEstimate rowsEnteringEstimate) {
9611025
double passRatio = newlyUnlockedFilterPassRatio(0L, seedMask, rowsEnteringEstimate);
@@ -2899,7 +2963,141 @@ private boolean isFactorActionLegal(int factorIndex, long boundVarMask) {
28992963
}
29002964

29012965
private long candidateActionsMask(StatePlan plan) {
2902-
return candidatesMask(plan) | availableFilterActionMask(plan);
2966+
long candidates = candidatesMask(plan);
2967+
candidates = delayFiniteCompletableLookupCandidates(plan, candidates);
2968+
candidates = delayUnfilteredFiniteAssignmentsUntilExactLookupGuards(plan, candidates);
2969+
candidates = preferBoundSubjectTypeGuards(plan.mask(), candidates);
2970+
return candidates | availableFilterActionMask(plan);
2971+
}
2972+
2973+
private long delayFiniteCompletableLookupCandidates(StatePlan plan, long candidates) {
2974+
long pendingAssignments = candidates & smallBindingSetAssignmentFactorMask;
2975+
if (pendingAssignments == 0L) {
2976+
return candidates;
2977+
}
2978+
long delayed = 0L;
2979+
long boundVarMask = plan.boundVarMask();
2980+
long pendingAssignmentVars = assignmentVariableMask(pendingAssignments) & ~boundVarMask;
2981+
long statementCandidates = candidates & ~bindingSetAssignmentFactorMask;
2982+
while (statementCandidates != 0L) {
2983+
int candidate = Long.numberOfTrailingZeros(statementCandidates);
2984+
statementCandidates &= statementCandidates - 1L;
2985+
if (statementPatternFactor(candidate) == null) {
2986+
continue;
2987+
}
2988+
FactorPhysicalEstimate physicalEstimate = factorPhysicalEstimate(candidate, plan.mask(), boundVarMask,
2989+
factorOutputRows[candidate], plan.estimate());
2990+
if (isExactStatementDirectLookup(physicalEstimate)) {
2991+
continue;
2992+
}
2993+
long missingLookupVars = missingExactLookupVariableMask(candidate,
2994+
physicalEstimate.lookupComponentMask(), boundVarMask);
2995+
if (missingLookupVars != 0L && (missingLookupVars & ~pendingAssignmentVars) == 0L) {
2996+
delayed |= bit(candidate);
2997+
continue;
2998+
}
2999+
if (shouldDelayBroadLookupForFinitePrefixGuard(physicalEstimate, missingLookupVars,
3000+
pendingAssignmentVars)) {
3001+
delayed |= bit(candidate);
3002+
}
3003+
}
3004+
return candidates & ~delayed;
3005+
}
3006+
3007+
private boolean shouldDelayBroadLookupForFinitePrefixGuard(FactorPhysicalEstimate physicalEstimate,
3008+
long missingLookupVars, long pendingAssignmentVars) {
3009+
if (physicalEstimate == null || missingLookupVars == 0L
3010+
|| (missingLookupVars & pendingAssignmentVars) == 0L
3011+
|| isExactStatementDirectLookup(physicalEstimate)) {
3012+
return false;
3013+
}
3014+
double currentAccessRows = physicalEstimate.accessRowsBeforeFilter();
3015+
if (!isFiniteNonNegative(currentAccessRows)) {
3016+
currentAccessRows = physicalEstimate.workRows();
3017+
}
3018+
if (!isFiniteNonNegative(currentAccessRows)) {
3019+
currentAccessRows = physicalEstimate.factorOutputRows();
3020+
}
3021+
return isFiniteNonNegative(currentAccessRows)
3022+
&& currentAccessRows >= FINITE_DOMAIN_PREFIX_GUARD_MIN_ACCESS_ROWS;
3023+
}
3024+
3025+
private long delayUnfilteredFiniteAssignmentsUntilExactLookupGuards(StatePlan plan, long candidates) {
3026+
long assignments = candidates & smallBindingSetAssignmentFactorMask;
3027+
if (assignments == 0L) {
3028+
return candidates;
3029+
}
3030+
long unfilteredAssignments = 0L;
3031+
long filterUnlockingAssignments = 0L;
3032+
long filterParticipatingAssignments = 0L;
3033+
long boundVarMask = plan.boundVarMask();
3034+
long remaining = assignments;
3035+
while (remaining != 0L) {
3036+
int assignment = Long.numberOfTrailingZeros(remaining);
3037+
remaining &= remaining - 1L;
3038+
long assignmentVars = bindingVarMasks[assignment] & ~boundVarMask;
3039+
if (assignmentVars == 0L) {
3040+
continue;
3041+
}
3042+
if (delayedFiniteFilterCount(boundVarMask, assignmentVars) > 0) {
3043+
filterUnlockingAssignments |= bit(assignment);
3044+
} else if (finiteFilterParticipationCount(assignmentVars) > 0) {
3045+
filterParticipatingAssignments |= bit(assignment);
3046+
} else {
3047+
unfilteredAssignments |= bit(assignment);
3048+
}
3049+
}
3050+
long preferredFiniteAssignments = filterUnlockingAssignments != 0L
3051+
? filterUnlockingAssignments
3052+
: filterParticipatingAssignments;
3053+
if (unfilteredAssignments == 0L
3054+
|| (preferredFiniteAssignments == 0L && pendingBoundExactLookupGuardMask(plan) == 0L)) {
3055+
return candidates;
3056+
}
3057+
return candidates & ~unfilteredAssignments;
3058+
}
3059+
3060+
private int finiteFilterParticipationCount(long assignmentVars) {
3061+
if (deferredFilters.isEmpty() || assignmentVars == 0L) {
3062+
return 0;
3063+
}
3064+
int count = 0;
3065+
for (int i = 0; i < plannedFilterActionCount(); i++) {
3066+
long requiredVars = deferredFilterRequiredVarMasks[i];
3067+
if (Long.bitCount(requiredVars) >= 2 && (requiredVars & assignmentVars) != 0L) {
3068+
count++;
3069+
}
3070+
}
3071+
return count;
3072+
}
3073+
3074+
private long assignmentVariableMask(long assignmentMask) {
3075+
long variables = 0L;
3076+
long assignments = assignmentMask;
3077+
while (assignments != 0L) {
3078+
int assignment = Long.numberOfTrailingZeros(assignments);
3079+
assignments &= assignments - 1L;
3080+
variables |= bindingVarMasks[assignment] & variableUniverseMask;
3081+
}
3082+
return variables;
3083+
}
3084+
3085+
private long missingExactLookupVariableMask(int factorIndex, int lookupComponentMask, long boundVarMask) {
3086+
StatementPattern statementPattern = statementPatternFactor(factorIndex);
3087+
if (statementPattern == null) {
3088+
return 0L;
3089+
}
3090+
long missingVars = 0L;
3091+
if ((lookupComponentMask & componentBit(SketchBasedJoinEstimator.Component.S)) == 0) {
3092+
missingVars |= variableMask(statementPattern.getSubjectVar()) & ~boundVarMask;
3093+
}
3094+
if ((lookupComponentMask & componentBit(SketchBasedJoinEstimator.Component.P)) == 0) {
3095+
missingVars |= variableMask(statementPattern.getPredicateVar()) & ~boundVarMask;
3096+
}
3097+
if ((lookupComponentMask & componentBit(SketchBasedJoinEstimator.Component.O)) == 0) {
3098+
missingVars |= variableMask(statementPattern.getObjectVar()) & ~boundVarMask;
3099+
}
3100+
return missingVars;
29033101
}
29043102

29053103
private long availableFilterActionMask(StatePlan plan) {
@@ -2908,9 +3106,53 @@ private long availableFilterActionMask(StatePlan plan) {
29083106
}
29093107
long filters = eligibleDeferredFilterMask(plan.boundVarMask(), plan.appliedFilterMask(),
29103108
plannedFilterMask & ~automaticFilterMask);
3109+
filters = delayNestedFilterActionsUntilBoundExactLookupGuardsRun(plan, filters);
29113110
return filters << factors.size();
29123111
}
29133112

3113+
private long delayNestedFilterActionsUntilBoundExactLookupGuardsRun(StatePlan plan, long filters) {
3114+
if (filters == 0L
3115+
|| (pendingSmallBindingAssignmentMask(plan) == 0L && pendingBoundExactLookupGuardMask(plan) == 0L)) {
3116+
return filters;
3117+
}
3118+
long blocked = 0L;
3119+
long remaining = filters;
3120+
while (remaining != 0L) {
3121+
int filterIndex = Long.numberOfTrailingZeros(remaining);
3122+
remaining &= remaining - 1L;
3123+
if (deferredFilters.get(filterIndex).hasNestedTupleExpression()) {
3124+
blocked |= bit(filterIndex);
3125+
}
3126+
}
3127+
return filters & ~blocked;
3128+
}
3129+
3130+
private long pendingSmallBindingAssignmentMask(StatePlan plan) {
3131+
return candidatesMask(plan) & smallBindingSetAssignmentFactorMask;
3132+
}
3133+
3134+
private long pendingBoundExactLookupGuardMask(StatePlan plan) {
3135+
long candidates = candidatesMask(plan) & ~bindingSetAssignmentFactorMask;
3136+
if (candidates == 0L) {
3137+
return 0L;
3138+
}
3139+
long boundVarMask = plan.boundVarMask();
3140+
long guards = 0L;
3141+
while (candidates != 0L) {
3142+
int candidate = Long.numberOfTrailingZeros(candidates);
3143+
candidates &= candidates - 1L;
3144+
if ((runtimeVarMasks[candidate] & ~boundVarMask) != 0L) {
3145+
continue;
3146+
}
3147+
FactorPhysicalEstimate physicalEstimate = factorPhysicalEstimate(candidate, plan.mask(), boundVarMask,
3148+
factorOutputRows[candidate], plan.estimate());
3149+
if (isExactStatementDirectLookup(physicalEstimate)) {
3150+
guards |= bit(candidate);
3151+
}
3152+
}
3153+
return guards;
3154+
}
3155+
29143156
private StatePlan applyAutomaticFilterActions(StatePlan plan) {
29153157
StatePlan current = plan;
29163158
while (automaticFilterMask != 0L) {
@@ -3154,6 +3396,9 @@ private double physicalRowFlowRows(int factorIndex, long mask,
31543396
double rowsPerInvocation = physicalEstimate.accessRowsBeforeFilter();
31553397
if (!isFiniteNonNegative(rowsPerInvocation)) {
31563398
rowsPerInvocation = physicalEstimate.factorOutputRows();
3399+
} else if (physicalEstimate.missingLookupComponents() > 0
3400+
&& isFiniteNonNegative(physicalEstimate.factorOutputRows())) {
3401+
rowsPerInvocation = Math.max(rowsPerInvocation, physicalEstimate.factorOutputRows());
31573402
}
31583403
if (!isFiniteNonNegative(rowsPerInvocation) || rowsPerInvocation <= 0.0d) {
31593404
return Double.NaN;
@@ -3224,6 +3469,16 @@ private boolean isExactStatementDirectLookup(SketchBasedJoinEstimator.AccessShap
32243469
&& accessShape.isDirectLookup(lookupBoundComponentMask);
32253470
}
32263471

3472+
private boolean isExactStatementDirectLookup(FactorPhysicalEstimate physicalEstimate) {
3473+
if (physicalEstimate == null || !physicalEstimate.directLookup()) {
3474+
return false;
3475+
}
3476+
int exactStatementMask = componentBit(SketchBasedJoinEstimator.Component.S)
3477+
| componentBit(SketchBasedJoinEstimator.Component.P)
3478+
| componentBit(SketchBasedJoinEstimator.Component.O);
3479+
return (physicalEstimate.lookupComponentMask() & exactStatementMask) == exactStatementMask;
3480+
}
3481+
32273482
private int componentBit(SketchBasedJoinEstimator.Component component) {
32283483
return 1 << component.ordinal();
32293484
}
@@ -6021,6 +6276,9 @@ private void addPhysicalMetrics(Map<String, String> stringMetrics, Map<String, D
60216276
}
60226277
stringMetrics.putAll(factorCostEstimate.getStringMetrics());
60236278
doubleMetrics.putAll(factorCostEstimate.getDoubleMetrics());
6279+
if (physicalEstimate.physicalComparable() && isFiniteNonNegative(physicalEstimate.workRows())) {
6280+
doubleMetrics.put(TelemetryMetricNames.PLANNED_ACCESS_WORK_ROWS, physicalEstimate.workRows());
6281+
}
60246282
}
60256283

60266284
private Set<String> sharedJoinVars(TupleExpr tupleExpr, Set<String> boundBefore) {

0 commit comments

Comments
 (0)