Skip to content

Commit

Permalink
fix for multiple vars in join and performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
hmottestad committed Oct 25, 2023
1 parent e62f375 commit 7a6763b
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
@Experimental
public class InnerMergeJoinIterator extends LookAheadIteration<BindingSet> {

private final CloseableIteration<BindingSet> leftIterator;
private final PeekMarkIterator<BindingSet> leftIterator;
private final PeekMarkIterator<BindingSet> rightIterator;
private final Comparator<Value> cmp;
private final Function<BindingSet, Value> value;
Expand All @@ -41,7 +41,7 @@ private InnerMergeJoinIterator(CloseableIteration<BindingSet> leftIterator,
CloseableIteration<BindingSet> rightIterator,
Comparator<Value> cmp, Function<BindingSet, Value> value, QueryEvaluationContext context)
throws QueryEvaluationException {
this.leftIterator = leftIterator;
this.leftIterator = new PeekMarkIterator<>(leftIterator);
this.rightIterator = new PeekMarkIterator<>(rightIterator);
this.cmp = cmp;
this.value = value;
Expand All @@ -68,8 +68,13 @@ public static CloseableIteration<BindingSet> getInstance(QueryEvaluationStep lef
BindingSet next;
BindingSet currentLeft;

BindingSet join(BindingSet left, BindingSet right) {
MutableBindingSet joined = context.createBindingSet(left);
BindingSet join(BindingSet left, BindingSet right, boolean createNewBindingSet) {
MutableBindingSet joined;
if (!createNewBindingSet && left instanceof MutableBindingSet) {
joined = (MutableBindingSet) left;
} else {
joined = context.createBindingSet(left);
}
for (Binding binding : right) {
if (!joined.hasBinding(binding.getName())) {
joined.addBinding(binding);
Expand All @@ -96,14 +101,27 @@ void calculateNext() {
BindingSet peekRight = rightIterator.peek();
Value left = value.apply(currentLeft);
Value right = value.apply(peekRight);

int compareTo = cmp.compare(left, right);
if (compareTo == 0) {
if (rightIterator.isResettable()) {
next = join(currentLeft, rightIterator.next());
next = join(currentLeft, rightIterator.next(), true);
return;
} else {
rightIterator.mark();
next = join(currentLeft, rightIterator.next());
BindingSet leftPeek = leftIterator.peek();
if (leftPeek != null && left.equals(value.apply(leftPeek))) {
rightIterator.mark();
next = join(currentLeft, rightIterator.next(), true);
} else {
BindingSet nextRight = rightIterator.next();
BindingSet rightPeek = rightIterator.peek();
if (rightPeek != null && right.equals(value.apply(rightPeek))) {
next = join(currentLeft, nextRight, true);
} else {
next = join(currentLeft, nextRight, false);
}
return;
}
return;
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ public ParentCheckingVisitor(QueryOptimizer previousOptimizerInPipeline) {
protected void meetNode(QueryModelNode node) throws RuntimeException {
QueryModelNode expectedParent = ancestors.peekLast();
if (node.getParentNode() != expectedParent) {
String message = "After " + previousOptimizer + " there was an unexpected parent for node " + node
+ ": " + node.getParentNode() + " (expected " + expectedParent + ")";
String message = "After " + previousOptimizer + " there was an unexpected parent for node \n" + node
+ "\nwith parent: \n" + node.getParentNode() + "\nexpected: \n" + expectedParent;
assert node.getParentNode() == expectedParent : message;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public void meet(Join node) {
TupleExpr tupleExpr = selectNextTupleExpr(joinArgs, cardinalityMap, varsMap, varFreqMap);

joinArgs.remove(tupleExpr);
orderedJoinArgs.add(tupleExpr);
orderedJoinArgs.addLast(tupleExpr);

// Recursively optimize join arguments
tupleExpr.visit(this);
Expand Down Expand Up @@ -233,11 +233,10 @@ public void meet(Join node) {
}

TupleExpr first = orderedJoinArgs.removeFirst();

TupleExpr second = orderedJoinArgs.removeFirst();
Set<Var> SupportedOrders = new HashSet<>(first.getSupportedOrders(tripleSource));
SupportedOrders.retainAll(second.getSupportedOrders(tripleSource));
if (SupportedOrders.isEmpty()) {
if (SupportedOrders.isEmpty() || joinOnMultipleVars(first, second)) {
orderedJoinArgs.addFirst(second);
orderedJoinArgs.addFirst(first);
break;
Expand Down Expand Up @@ -285,6 +284,29 @@ public void meet(Join node) {
}
}

private boolean joinOnMultipleVars(TupleExpr first, TupleExpr second) {
Set<String> firstBindingNames = first.getBindingNames();
if (firstBindingNames.size() == 1) {
return false;
}
Set<String> secondBindingNames = second.getBindingNames();
if (secondBindingNames.size() == 1) {
return false;
}
int overlap = 0;
for (String firstBindingName : firstBindingNames) {
if (secondBindingNames.contains(firstBindingName)) {
overlap++;
}
if (overlap > 1) {
return true;
}
}

return false;

}

protected <L extends List<TupleExpr>> L getJoinArgs(TupleExpr tupleExpr, L joinArgs) {
if (tupleExpr instanceof Join) {
Join join = (Join) tupleExpr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ public Iterable<QueryOptimizer> getOptimizers() {
new QueryJoinOptimizer(evaluationStatistics, strategy.isTrackResultSize(), tripleSource),
ITERATIVE_EVALUATION_OPTIMIZER,
FILTER_OPTIMIZER,
ORDER_LIMIT_OPTIMIZER);
ORDER_LIMIT_OPTIMIZER
);

if (assertsEnabled) {
List<QueryOptimizer> optimizersWithReferenceCleaner = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public String toString() {

@Override
public Explanation explain(Explanation.Level level) {
throw new UnsupportedOperationException();
return sailQuery.explain(level);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public Explanation explain(Explanation.Level level) {
timeout = getMaxExecutionTime();
}

TupleExpr tupleExpr = getParsedQuery().getTupleExpr();
TupleExpr tupleExpr = getParsedQuery().getTupleExpr().clone();

// That query has a root does not add to the explanation.
if (tupleExpr instanceof QueryRoot) {
Expand Down

0 comments on commit 7a6763b

Please sign in to comment.