Skip to content

Commit 797f25f

Browse files
authored
drop sorts in cross joins and inner joins (#3117)
1 parent 8c67f47 commit 797f25f

File tree

2 files changed

+293
-22
lines changed

2 files changed

+293
-22
lines changed

enginetest/queries/query_plan_script_tests.go

Lines changed: 258 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sql/analyzer/replace_sort.go

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,16 @@ func replaceIdxSortHelper(ctx *sql.Context, scope *plan.Scope, node sql.Node, so
154154
*plan.Project, *plan.Filter, *plan.Limit, *plan.Offset, *plan.Distinct, *plan.TableAlias:
155155
newChildren[i], same, err = replaceIdxSortHelper(ctx, scope, child, sortNode)
156156
case *plan.JoinNode:
157-
// TODO: is this applicable to other types of joins?
158-
// as long as left child is already sorted and SortFields are a prefix, then it's ok?
159-
if !c.JoinType().IsMerge() {
160-
continue
161-
}
162157
// It's (probably) not possible to have Sort as child of Join without Subquery/SubqueryAlias,
163158
// and in the case where there is a Subq/SQA it's taken care of through finalizeSubqueries
164159
if sortNode == nil {
165160
continue
166161
}
162+
// Merge Joins assume that left and right are sorted
163+
// Cross Joins and Inner Joins are valid for sort removal if left child is sorted
164+
if !c.JoinType().IsMerge() && !c.JoinType().IsCross() && !c.JoinType().IsInner() {
165+
continue
166+
}
167167
newLeft, sameLeft, errLeft := replaceIdxSortHelper(ctx, scope, c.Left(), sortNode)
168168
if errLeft != nil {
169169
return nil, transform.SameTree, errLeft
@@ -172,35 +172,48 @@ func replaceIdxSortHelper(ctx *sql.Context, scope *plan.Scope, node sql.Node, so
172172
if errRight != nil {
173173
return nil, transform.SameTree, errRight
174174
}
175-
if sameLeft && sameRight {
175+
// Neither child was converted to an IndexedTableAccess, so we can't remove the sort node
176+
leftIsSorted, rightIsSorted := !sameLeft, !sameRight
177+
if !leftIsSorted && !rightIsSorted {
176178
continue
177179
}
178180
// No need to check all SortField orders because of isValidSortFieldOrder
179181
isReversed := sortNode.SortFields[0].Order == sql.Descending
180182
// If both left and right have been replaced, no need to manually reverse any indexes as they both should be
181183
// replaced already
182-
if !sameLeft && !sameRight {
184+
if leftIsSorted && rightIsSorted {
183185
c.IsReversed = isReversed
184186
continue
185187
}
186-
// If only one side has been replaced, we need to check if the other side can be reversed
187-
if (sameLeft != sameRight) && isReversed {
188-
// If descending, then both Indexes must be reversed
189-
if sameLeft {
190-
newLeft, same, err = buildReverseIndexedTable(ctx, newLeft)
191-
} else if sameRight {
192-
newRight, same, err = buildReverseIndexedTable(ctx, newRight)
188+
if c.JoinType().IsCross() || c.JoinType().IsInner() {
189+
// For cross joins and inner joins, if the right child is sorted, we need to swap
190+
if !sameRight {
191+
// Swapping may mess up projections, but
192+
// eraseProjection will drop any Projections that are now unnecessary and
193+
// fixExecIndexes will fix any existing Projection GetField indexes.
194+
newLeft, newRight = newRight, newLeft
193195
}
194-
if err != nil {
195-
return nil, transform.SameTree, err
196+
} else {
197+
// If only one side has been replaced, we need to check if the other side can be reversed
198+
if (leftIsSorted != rightIsSorted) && isReversed {
199+
// If descending, then both Indexes must be reversed
200+
if rightIsSorted {
201+
newLeft, same, err = buildReverseIndexedTable(ctx, newLeft)
202+
} else if leftIsSorted {
203+
newRight, same, err = buildReverseIndexedTable(ctx, newRight)
204+
}
205+
if err != nil {
206+
return nil, transform.SameTree, err
207+
}
208+
// If we could not replace the IndexedTableAccess with a reversed one (due to lack of reversible index)
209+
// same = true, so just continue
210+
if same {
211+
continue
212+
}
213+
c.IsReversed = true
196214
}
197-
// If we could not replace the IndexedTableAccess with a reversed one (due to lack of reversible index)
198-
// same = true, so just continue
199-
if same {
200-
continue
201-
}
202-
c.IsReversed = true
203215
}
216+
204217
newChildren[i], err = c.WithChildren(newLeft, newRight)
205218
if err != nil {
206219
return nil, transform.SameTree, err

0 commit comments

Comments
 (0)