Skip to content

Commit 2f14366

Browse files
committed
improvements
1 parent 303d19b commit 2f14366

2 files changed

Lines changed: 172 additions & 0 deletions

File tree

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbDeferredFilterPlacer.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.eclipse.rdf4j.model.vocabulary.RDF;
2626
import org.eclipse.rdf4j.query.algebra.Compare;
27+
import org.eclipse.rdf4j.query.algebra.Exists;
2728
import org.eclipse.rdf4j.query.algebra.Filter;
2829
import org.eclipse.rdf4j.query.algebra.Not;
2930
import org.eclipse.rdf4j.query.algebra.StatementPattern;
@@ -300,6 +301,12 @@ private boolean canApplyDeferredFilterToBindingPrefix(DeferredFilter deferredFil
300301
return false;
301302
}
302303
Set<String> conditionBindingNames = conditionBindingNames(deferredFilter);
304+
return canApplyDeferredFilterToBindingPrefix(deferredFilter, prefixBindingNames, availableNames,
305+
assignmentBindingNames, conditionBindingNames);
306+
}
307+
308+
private boolean canApplyDeferredFilterToBindingPrefix(DeferredFilter deferredFilter, Set<String> prefixBindingNames,
309+
Set<String> availableNames, Set<String> assignmentBindingNames, Set<String> conditionBindingNames) {
303310
return !conditionBindingNames.isEmpty()
304311
&& (deferredFilter.conditionCost > JoinOrderPlanner.FILTER_COST_CHEAP
305312
|| !Collections.disjoint(prefixBindingNames, conditionBindingNames))
@@ -383,6 +390,9 @@ private boolean groupDeferredFilterOnSmallestWindow(List<SegmentFactor> factors,
383390
if (groupDeferredFilterOnBindingAssignments(factors, filter, boundBeforeSegment)) {
384391
return true;
385392
}
393+
if (groupDeferredFilterOnBindingPrefix(factors, filter, boundBeforeSegment)) {
394+
return true;
395+
}
386396
if (filter.conditionCost == JoinOrderPlanner.FILTER_COST_CHEAP) {
387397
window = smallestSinglePatternBindingCoveringWindow(factors, filter.requiredVars, boundBeforeSegment);
388398
if (window != null) {
@@ -483,6 +493,7 @@ private boolean groupDeferredFilterOnPlannerWindow(List<SegmentFactor> factors,
483493
if (targetIndex < 0) {
484494
return false;
485495
}
496+
targetIndex = expandCorrelatedExistsWindowOverLocalFilters(factors, filter, targetIndex);
486497
Set<String> availableNames = new HashSet<>(boundBeforeSegment);
487498
for (int i = 0; i <= targetIndex; i++) {
488499
availableNames.addAll(factors.get(i).bindingNames);
@@ -504,6 +515,43 @@ private int factorIndexForPlannerStep(List<SegmentFactor> factors, int targetSte
504515
return -1;
505516
}
506517

518+
private int expandCorrelatedExistsWindowOverLocalFilters(List<SegmentFactor> factors, DeferredFilter filter,
519+
int targetIndex) {
520+
if (!isCorrelatedExistsFilter(filter)) {
521+
return targetIndex;
522+
}
523+
int end = targetIndex;
524+
while (end + 1 < factors.size() && isCheapLocalFilterForCorrelatedFilter(factors.get(end + 1), filter)) {
525+
end++;
526+
}
527+
return end;
528+
}
529+
530+
private boolean isCorrelatedExistsFilter(DeferredFilter filter) {
531+
return !filter.requiredVars.isEmpty()
532+
&& filter.condition instanceof Exists;
533+
}
534+
535+
private boolean isCheapLocalFilterForCorrelatedFilter(SegmentFactor factor, DeferredFilter filter) {
536+
return !Collections.disjoint(factor.bindingNames, filter.requiredVars)
537+
&& containsNonExistsFilter(factor.tupleExpr);
538+
}
539+
540+
private boolean containsNonExistsFilter(TupleExpr tupleExpr) {
541+
boolean[] contains = { false };
542+
tupleExpr.visit(new AbstractSimpleQueryModelVisitor<RuntimeException>() {
543+
@Override
544+
public void meet(Filter node) {
545+
if (!LmdbJoinPlanSupport.containsExists(node.getCondition())) {
546+
contains[0] = true;
547+
return;
548+
}
549+
super.meet(node);
550+
}
551+
});
552+
return contains[0];
553+
}
554+
507555
private boolean isCorrelatedNotExistsFilter(DeferredFilter filter) {
508556
return !filter.requiredVars.isEmpty()
509557
&& filter.condition instanceof Not not
@@ -573,6 +621,44 @@ private boolean groupDeferredFilterOnBindingAssignments(List<SegmentFactor> fact
573621
return true;
574622
}
575623

624+
private boolean groupDeferredFilterOnBindingPrefix(List<SegmentFactor> factors,
625+
DeferredFilter deferredFilter, Set<String> boundBeforeSegment) {
626+
if (LmdbJoinPlanSupport.containsExists(deferredFilter.condition)) {
627+
return false;
628+
}
629+
Set<String> conditionBindingNames = conditionBindingNames(deferredFilter);
630+
if (conditionBindingNames.isEmpty()) {
631+
return false;
632+
}
633+
Set<String> prefixBindingNames = new HashSet<>(boundBeforeSegment);
634+
for (int i = 0; i < factors.size(); i++) {
635+
SegmentFactor factor = factors.get(i);
636+
if (LmdbJoinPlanSupport.isBindingOnlyFactor(factor)) {
637+
Set<String> assignmentBindingNames = plannerBindingNames(factor.bindingNames);
638+
Set<String> availableNames = new HashSet<>(prefixBindingNames);
639+
availableNames.addAll(assignmentBindingNames);
640+
if (canApplyDeferredFilterToBindingPrefix(deferredFilter, prefixBindingNames, availableNames,
641+
assignmentBindingNames, conditionBindingNames)) {
642+
TupleExpr filteredRoot = filterWrapper.wrap(factor.tupleExpr, List.of(deferredFilter),
643+
"bindingPrefix");
644+
factors.set(i, new SegmentFactor(filteredRoot, factor.containedPatterns, factor.firstFactorOrder,
645+
factor.lastFactorOrder));
646+
return true;
647+
}
648+
}
649+
prefixBindingNames.addAll(prefixVisibleBindingNames(factor));
650+
}
651+
return false;
652+
}
653+
654+
private Set<String> prefixVisibleBindingNames(SegmentFactor factor) {
655+
Set<String> bindingNames = new HashSet<>(plannerBindingNames(factor.bindingNames));
656+
for (StatementPattern pattern : factor.containedPatterns) {
657+
bindingNames.addAll(plannerBindingNames(pattern.getBindingNames()));
658+
}
659+
return bindingNames;
660+
}
661+
576662
private boolean selectedIndexesAreContiguous(List<Integer> selectedIndexes) {
577663
for (int i = 1; i < selectedIndexes.size(); i++) {
578664
if (selectedIndexes.get(i).intValue() != selectedIndexes.get(i - 1).intValue() + 1) {

core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/LmdbSketchJoinOptimizer.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ final class LmdbSketchJoinOptimizer implements QueryOptimizer {
7676
private static final int CANONICAL_FINITE_ANCHOR_LITERAL_FILTER_SCORE = 50;
7777
private static final int CANONICAL_FINITE_ANCHOR_ULTRA_SELECTIVE_FILTER_SCORE = 950;
7878
private static final int CORRELATED_ANTI_JOIN_COMPLEX_SUFFIX_PATTERN_LIMIT = 3;
79+
private static final String LMDB_SKETCH_PLANNER_ID = "lmdb-sketch";
7980
private static final String FINITE_ANCHOR_PLANNER_ID = "lmdb-finite-anchor";
8081
private static final String FINITE_ANCHOR_PLANNER_PATH = "CANONICAL_FINITE_ANCHOR";
8182
private static final String LMDB_PHYSICAL_REFINEMENT = "costModel=lmdb, accessPathSelection=per-step";
@@ -226,6 +227,9 @@ private TupleExpr rewriteNullRejectingOptionalFilter(Filter filter, LeftJoin lef
226227
if (finiteLeftBindingsCoverOptionalProbeInput(leftJoin, optionalBindings)) {
227228
return null;
228229
}
230+
if (containsNestedExistsFilter(leftJoin.getLeftArg())) {
231+
return null;
232+
}
229233
TupleExpr replacement = rewriteNullRejectingOptionalFilterAfterDelayableExtension(filter, leftJoin);
230234
if (replacement == null) {
231235
replacement = new Filter(new Join(leftJoin.getLeftArg().clone(), leftJoin.getRightArg().clone()),
@@ -276,6 +280,21 @@ public void meet(BindingSetAssignment assignment) {
276280
return bindingNames;
277281
}
278282

283+
private boolean containsNestedExistsFilter(TupleExpr tupleExpr) {
284+
boolean[] contains = { false };
285+
tupleExpr.visit(new AbstractSimpleQueryModelVisitor<RuntimeException>() {
286+
@Override
287+
public void meet(Filter node) {
288+
if (LmdbJoinPlanSupport.containsExists(node.getCondition())) {
289+
contains[0] = true;
290+
return;
291+
}
292+
super.meet(node);
293+
}
294+
});
295+
return contains[0];
296+
}
297+
279298
private Set<String> extensionElementNames(TupleExpr tupleExpr) {
280299
Set<String> names = new HashSet<>();
281300
tupleExpr.visit(new AbstractSimpleQueryModelVisitor<RuntimeException>() {
@@ -438,6 +457,9 @@ private TupleExpr rewriteNoNewBindingOptionalProbe(LeftJoin leftJoin) {
438457
}
439458

440459
private TupleExpr rewriteNoNewBindingExistsProbe(Filter filter) {
460+
if (filter.getArg() instanceof Join && !LmdbJoinPlanSupport.isJoinOrderSeparator(filter.getArg())) {
461+
return null;
462+
}
441463
TupleExpr replacement = noNewBindingExistsProbeJoin(filter.getArg(), filter.getCondition(), true);
442464
if (replacement == null) {
443465
return null;
@@ -2466,6 +2488,12 @@ private TupleExpr wrapTupleExprWithDeferredFilters(TupleExpr root, List<Deferred
24662488
}
24672489

24682490
private TupleExpr applyFilter(TupleExpr root, DeferredFilter deferredFilter, String placement) {
2491+
if ("root".equals(placement)) {
2492+
TupleExpr relocated = relocateRootFilterToRightBindingPrefix(root, deferredFilter);
2493+
if (relocated != null) {
2494+
return relocated;
2495+
}
2496+
}
24692497
Filter filter = new Filter(root, deferredFilter.condition.clone());
24702498
optimizeConditionSubqueries(filter.getCondition(), filterConditionBindings(root),
24712499
estimatedSubplanInvocationRows(root), root);
@@ -2484,6 +2512,57 @@ private TupleExpr applyFilter(TupleExpr root, DeferredFilter deferredFilter, Str
24842512
return filter;
24852513
}
24862514

2515+
private TupleExpr relocateRootFilterToRightBindingPrefix(TupleExpr root, DeferredFilter deferredFilter) {
2516+
if (LmdbJoinPlanSupport.containsExists(deferredFilter.condition) || !(root instanceof Join)) {
2517+
return null;
2518+
}
2519+
Join join = (Join) root;
2520+
Optional<Set<String>> assignmentNames = LmdbJoinPlanSupport.positionableBindingSetAssignmentNames(
2521+
join.getRightArg());
2522+
if (assignmentNames.isEmpty()) {
2523+
return null;
2524+
}
2525+
Set<String> conditionBindingNames = plannerBindingNames(VarNameCollector.process(deferredFilter.condition));
2526+
if (conditionBindingNames.isEmpty()) {
2527+
return null;
2528+
}
2529+
Set<String> prefixBindingNames = visibleBindingNames(join.getLeftArg());
2530+
Set<String> assignmentBindingNames = plannerBindingNames(assignmentNames.get());
2531+
Set<String> availableNames = new HashSet<>(prefixBindingNames);
2532+
availableNames.addAll(assignmentBindingNames);
2533+
if (prefixBindingNames.containsAll(conditionBindingNames)
2534+
|| !availableNames.containsAll(conditionBindingNames)
2535+
|| Collections.disjoint(assignmentBindingNames, conditionBindingNames)
2536+
|| (!assignmentBindingNames.containsAll(conditionBindingNames)
2537+
&& containsNotEquals(deferredFilter.condition))) {
2538+
return null;
2539+
}
2540+
join.setRightArg(applyFilter(join.getRightArg(), deferredFilter, "bindingPrefix"));
2541+
return join;
2542+
}
2543+
2544+
private Set<String> visibleBindingNames(TupleExpr tupleExpr) {
2545+
Set<String> bindingNames = new HashSet<>(plannerBindingNames(tupleExpr.getBindingNames()));
2546+
for (StatementPattern pattern : LmdbJoinPlanSupport.collectPatternIdentities(tupleExpr)) {
2547+
bindingNames.addAll(plannerBindingNames(pattern.getBindingNames()));
2548+
}
2549+
return bindingNames;
2550+
}
2551+
2552+
private boolean containsNotEquals(ValueExpr condition) {
2553+
boolean[] contains = { false };
2554+
condition.visit(new AbstractSimpleQueryModelVisitor<RuntimeException>() {
2555+
@Override
2556+
public void meet(Compare node) {
2557+
if (node.getOperator() == Compare.CompareOp.NE) {
2558+
contains[0] = true;
2559+
}
2560+
super.meet(node);
2561+
}
2562+
});
2563+
return contains[0];
2564+
}
2565+
24872566
private Join createJoin(TupleExpr left, TupleExpr right) {
24882567
Join join = new Join(left, right);
24892568
double rows = syntheticJoinResultEstimate(left, right);
@@ -2603,6 +2682,13 @@ private void applyFiniteAnchorPlannerMetrics(List<TupleExpr> orderedArgs) {
26032682
root.setStringMetricPlanned(TelemetryMetricNames.PLANNER_PATH, FINITE_ANCHOR_PLANNER_PATH);
26042683
root.setStringMetricPlanned(TelemetryMetricNames.OPTIMIZER_PHYSICAL_REFINEMENT,
26052684
LMDB_PHYSICAL_REFINEMENT);
2685+
for (int i = 1; i < orderedArgs.size(); i++) {
2686+
TupleExpr tupleExpr = orderedArgs.get(i);
2687+
if (!LmdbJoinPlanSupport.collectPatternIdentities(tupleExpr).isEmpty()) {
2688+
tupleExpr.setStringMetricPlanned(TelemetryMetricNames.PLANNER_ID, LMDB_SKETCH_PLANNER_ID);
2689+
return;
2690+
}
2691+
}
26062692
}
26072693

26082694
private final class AntiJoinCost {

0 commit comments

Comments
 (0)