Skip to content

Commit

Permalink
Reduce custom sorts on merge joins
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkMpn committed Nov 2, 2023
1 parent 1ca1381 commit 1770472
Showing 1 changed file with 34 additions and 41 deletions.
75 changes: 34 additions & 41 deletions MarkMpn.Sql4Cds.Engine/ExecutionPlan/MergeJoinNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,23 @@ public override IDataExecutionPlanNodeInternal FoldQuery(NodeCompilationContext
if (folded != this)
return folded;

var hashJoin = new HashJoinNode
{
LeftSource = LeftSource,
RightSource = RightSource,
LeftAttribute = LeftAttribute,
RightAttribute = RightAttribute,
JoinType = JoinType,
AdditionalJoinCriteria = AdditionalJoinCriteria,
SemiJoin = SemiJoin
};

foreach (var kvp in DefinedValues)
hashJoin.DefinedValues.Add(kvp);

hashJoin.LeftSource.Parent = hashJoin;
hashJoin.RightSource.Parent = hashJoin;

// Can't use a merge join if the join key types have different sort orders
if (LeftAttribute != null && RightAttribute != null)
{
Expand All @@ -229,26 +246,7 @@ public override IDataExecutionPlanNodeInternal FoldQuery(NodeCompilationContext
var rightType = rightSchema.Schema[rightColumn].Type;

if (!IsConsistentSortTypes(leftType, rightType))
{
var hashJoin = new HashJoinNode
{
LeftSource = LeftSource,
RightSource = RightSource,
LeftAttribute = LeftAttribute,
RightAttribute = RightAttribute,
JoinType = JoinType,
AdditionalJoinCriteria = AdditionalJoinCriteria,
SemiJoin = SemiJoin
};

foreach (var kvp in DefinedValues)
hashJoin.DefinedValues.Add(kvp);

hashJoin.LeftSource.Parent = hashJoin;
hashJoin.RightSource.Parent = hashJoin;

return hashJoin;
}
return hashJoin.FoldQuery(context, hints);
}

// This is a many-to-many join if the left attribute is not unique
Expand Down Expand Up @@ -301,27 +299,22 @@ public override IDataExecutionPlanNodeInternal FoldQuery(NodeCompilationContext
// If we couldn't fold the sorts, it's probably faster to use a hash join instead if we only want partial results
var leftSort = LeftSource as SortNode;
var rightSort = RightSource as SortNode;
if (Parent is TopNode && (leftSort != null || rightSort != null))
{
var hashJoin = new HashJoinNode
{
LeftSource = leftSort?.Source ?? LeftSource,
RightSource = rightSort?.Source ?? RightSource,
LeftAttribute = LeftAttribute,
RightAttribute = RightAttribute,
JoinType = JoinType,
AdditionalJoinCriteria = AdditionalJoinCriteria,
SemiJoin = SemiJoin
};

foreach (var kvp in DefinedValues)
hashJoin.DefinedValues.Add(kvp);

hashJoin.LeftSource.Parent = hashJoin;
hashJoin.RightSource.Parent = hashJoin;

return hashJoin;
}

if (leftSort == null && rightSort == null)
return this;

hashJoin.LeftSource = leftSort?.Source ?? LeftSource;
hashJoin.RightSource = rightSort?.Source ?? RightSource;


var foldedHashJoin = hashJoin.FoldQuery(context, hints);

if (Parent is TopNode ||
leftSort != null && rightSort != null)
return foldedHashJoin;

LeftSource.Parent = this;
RightSource.Parent = this;

return this;
}
Expand Down

0 comments on commit 1770472

Please sign in to comment.