Skip to content

Commit

Permalink
feat: add logic to better merge dual queries
Browse files Browse the repository at this point in the history
Signed-off-by: Manan Gupta <manan@planetscale.com>
  • Loading branch information
GuptaManan100 committed May 28, 2024
1 parent e912c3c commit 8d67079
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 21 deletions.
41 changes: 40 additions & 1 deletion go/vt/vtgate/planbuilder/operators/join_merging.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func mergeJoinInputs(ctx *plancontext.PlanningContext, lhs, rhs Operator, joinPr
switch {
case a == dual:
// If a dual is on the left side and it is a left join (all right joins are changed to left joins), then we can only merge if the right side is a single sharded routing.
if !m.joinType.IsInner() && !routingB.OpCode().IsSingleShard() {
if !m.joinType.IsInner() && !willBecomeSingleShardOnFilter(ctx, rhsRoute, joinPredicates) {
return nil
}
return m.merge(ctx, lhsRoute, rhsRoute, routingB)
Expand Down Expand Up @@ -69,6 +69,45 @@ func mergeJoinInputs(ctx *plancontext.PlanningContext, lhs, rhs Operator, joinPr
}
}

// willBecomeSingleShardOnFilter returns whether the given route will become a single sharded route after pushing the join predicates.
func willBecomeSingleShardOnFilter(ctx *plancontext.PlanningContext, a *Route, joinPredicates []sqlparser.Expr) bool {
// If the routing is already single sharded, it will remain so even after we push more predicates.
if a.Routing.OpCode().IsSingleShard() {
return true
}

// Go over all the join predicates.
for _, predicate := range joinPredicates {
comparison, ok := predicate.(*sqlparser.ComparisonExpr)
if !ok {
continue
}
if comparison.Operator != sqlparser.EqualOp {
continue
}
left := comparison.Left
right := comparison.Right

lVindex := findColumnVindex(ctx, a, left)
if lVindex == nil {
left, right = right, left
lVindex = findColumnVindex(ctx, a, left)
}

if lVindex == nil || !lVindex.IsUnique() {
continue
}
// If the predicate is an equal comparison with the left side having a unique column vindex,
// and the right side is a literal, then we know
// pushing this predicate will make the route a single sharded route.
if sqlparser.IsLiteral(right) {
return true
}
}

return false
}

func prepareInputRoutes(lhs Operator, rhs Operator) (*Route, *Route, Routing, Routing, routingType, routingType, bool) {
lhsRoute, rhsRoute := operatorsToRoutes(lhs, rhs)
if lhsRoute == nil || rhsRoute == nil {
Expand Down
78 changes: 58 additions & 20 deletions go/vt/vtgate/planbuilder/testdata/select_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -2044,11 +2044,34 @@
}
},
{
"comment": "left join with a dual table on left",
"comment": "left join with a dual table on left - merge-able",
"query": "select t.title, user.col from (select 'hello' as title) as t left join user on user.id=1",
"plan": {
"QueryType": "SELECT",
"Original": "select t.title, user.col from (select 'hello' as title) as t left join user on user.id=1",
"Instructions": {
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select t.title, `user`.col from (select 'hello' as title from dual where 1 != 1) as t left join `user` on `user`.id = 1 where 1 != 1",
"Query": "select t.title, `user`.col from (select 'hello' as title from dual) as t left join `user` on `user`.id = 1",
"Table": "`user`, dual"
},
"TablesUsed": [
"main.dual",
"user.user"
]
}
},
{
"comment": "left join with a dual table on left - non-merge-able",
"query": "select t.title, user.col from (select 'hello' as title) as t left join user on user.id <= 4",
"plan": {
"QueryType": "SELECT",
"Original": "select t.title, user.col from (select 'hello' as title) as t left join user on user.id <= 4",
"Instructions": {
"OperatorType": "Join",
"Variant": "LeftJoin",
Expand All @@ -2068,18 +2091,14 @@
},
{
"OperatorType": "Route",
"Variant": "EqualUnique",
"Variant": "Scatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select `user`.col from `user` where 1 != 1",
"Query": "select `user`.col from `user` where `user`.id = 1",
"Table": "`user`",
"Values": [
"1"
],
"Vindex": "user_index"
"Query": "select `user`.col from `user` where `user`.id <= 4",
"Table": "`user`"
}
]
},
Expand All @@ -2091,19 +2110,19 @@
},
{
"comment": "right join with a dual table on left",
"query": "select t.title, user.col from (select 'hello' as title) as t right join user on user.id=1",
"query": "select t.title, user.col from (select 'hello' as title) as t right join user on user.id<=4",
"plan": {
"QueryType": "SELECT",
"Original": "select t.title, user.col from (select 'hello' as title) as t right join user on user.id=1",
"Original": "select t.title, user.col from (select 'hello' as title) as t right join user on user.id<=4",
"Instructions": {
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select t.title, `user`.col from `user` left join (select 'hello' as title from dual where 1 != 1) as t on `user`.id = 1 where 1 != 1",
"Query": "select t.title, `user`.col from `user` left join (select 'hello' as title from dual) as t on `user`.id = 1",
"FieldQuery": "select t.title, `user`.col from `user` left join (select 'hello' as title from dual where 1 != 1) as t on `user`.id <= 4 where 1 != 1",
"Query": "select t.title, `user`.col from `user` left join (select 'hello' as title from dual) as t on `user`.id <= 4",
"Table": "`user`, dual"
},
"TablesUsed": [
Expand All @@ -2113,11 +2132,34 @@
}
},
{
"comment": "right join with a dual table on right",
"comment": "right join with a dual table on right - merge-able",
"query": "select t.title, user.col from user right join (select 'hello' as title) as t on user.id=1",
"plan": {
"QueryType": "SELECT",
"Original": "select t.title, user.col from user right join (select 'hello' as title) as t on user.id=1",
"Instructions": {
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select t.title, `user`.col from (select 'hello' as title from dual where 1 != 1) as t left join `user` on `user`.id = 1 where 1 != 1",
"Query": "select t.title, `user`.col from (select 'hello' as title from dual) as t left join `user` on `user`.id = 1",
"Table": "`user`, dual"
},
"TablesUsed": [
"main.dual",
"user.user"
]
}
},
{
"comment": "right join with a dual table on right - non-merge-able",
"query": "select t.title, user.col from user right join (select 'hello' as title) as t on user.id>=4",
"plan": {
"QueryType": "SELECT",
"Original": "select t.title, user.col from user right join (select 'hello' as title) as t on user.id>=4",
"Instructions": {
"OperatorType": "Join",
"Variant": "LeftJoin",
Expand All @@ -2137,18 +2179,14 @@
},
{
"OperatorType": "Route",
"Variant": "EqualUnique",
"Variant": "Scatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select `user`.col from `user` where 1 != 1",
"Query": "select `user`.col from `user` where `user`.id = 1",
"Table": "`user`",
"Values": [
"1"
],
"Vindex": "user_index"
"Query": "select `user`.col from `user` where `user`.id >= 4",
"Table": "`user`"
}
]
},
Expand Down

0 comments on commit 8d67079

Please sign in to comment.