Skip to content

Commit 1adb1db

Browse files
authored
Better join commutativity count (#1051)
We excluded joins on the basis of join factors in the logical join tree, rather than distinct join subtrees subject to commutativity. The difference is that we have to permute n! to optimize the search space of all valid commutative trees, versus a k^n (k = table rows) execution runtime. 12! blocks analysis, k^12 is steep but can be OK depending on cardinality and indexes. We impose no limits on k^n joins.
1 parent 96aa709 commit 1adb1db

File tree

4 files changed

+14
-32
lines changed

4 files changed

+14
-32
lines changed

enginetest/queries/queries.go

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8491,26 +8491,6 @@ var ErrorQueries = []QueryErrorTest{
84918491
t14.i = t15.i`,
84928492
ExpectedErr: sql.ErrUnsupportedJoinFactorCount,
84938493
},
8494-
{
8495-
Query: `SELECT t1.*
8496-
FROM
8497-
mytable as t1,
8498-
mytable as t2,
8499-
mytable as t3,
8500-
mytable as t4,
8501-
mytable as t5,
8502-
mytable as t6,
8503-
mytable as t7,
8504-
mytable as t8,
8505-
mytable as t9,
8506-
mytable as t10,
8507-
mytable as t11,
8508-
mytable as t12,
8509-
mytable as t13,
8510-
mytable as t14,
8511-
mytable as t15`,
8512-
ExpectedErr: sql.ErrUnsupportedJoinFactorCount,
8513-
},
85148494
{
85158495
Query: `SELECT t1.*
85168496
FROM

sql/analyzer/indexed_joins.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,10 @@ func replanJoin(
403403
joinHint := extractJoinHint(node)
404404

405405
// Collect all tables
406-
tableJoinOrder := newJoinOrderNode(node)
406+
tableJoinOrder, cnt := newJoinOrderNode(node)
407+
if cnt > joinComplexityLimit {
408+
return nil, transform.SameTree, sql.ErrUnsupportedJoinFactorCount.New(joinComplexityLimit, cnt)
409+
}
407410

408411
// Find a hinted or cost optimized access order for them
409412
ordered := false

sql/analyzer/join_search.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -413,22 +413,22 @@ func visitCommutableJoinSearchNodes(indexes []int, nodes []joinOrderNode, cb fun
413413
// table, table alias or subquery alias gets a leaf node, a sequence
414414
// of commutable joins get coalesced into a single node with children
415415
// set in `commutes`, and a left or right join gets a node with a
416-
// `left` and a `right` child. original on the left and the new table
417-
// being joined on the right.
418-
func newJoinOrderNode(node sql.Node) *joinOrderNode {
416+
// `left` and a `right` child original on the left and the new table
417+
// being joined on the right. Returns a tree's root and node count.
418+
func newJoinOrderNode(node sql.Node) (*joinOrderNode, int) {
419419
switch node := node.(type) {
420420
case *plan.TableAlias, *plan.ResolvedTable, *plan.SubqueryAlias, *plan.ValueDerivedTable:
421421
n := node.(NameableNode)
422-
return &joinOrderNode{node: n, name: strings.ToLower(n.Name())}
422+
return &joinOrderNode{node: n, name: strings.ToLower(n.Name())}, 1
423423
case *plan.CrossJoin:
424-
return &joinOrderNode{node: node}
424+
return &joinOrderNode{node: node}, 1
425425
case plan.JoinNode:
426-
ljo := newJoinOrderNode(node.Left())
427-
rjo := newJoinOrderNode(node.Right())
426+
ljo, lcnt := newJoinOrderNode(node.Left())
427+
rjo, rcnt := newJoinOrderNode(node.Right())
428428
if node.JoinType() == plan.JoinTypeLeft {
429-
return &joinOrderNode{left: ljo, right: rjo}
429+
return &joinOrderNode{left: ljo, right: rjo}, lcnt + rcnt
430430
} else if node.JoinType() == plan.JoinTypeRight {
431-
return &joinOrderNode{left: rjo, right: ljo}
431+
return &joinOrderNode{left: rjo, right: ljo}, lcnt + rcnt
432432
} else {
433433
commutes := append(ljo.commutes, rjo.commutes...)
434434
if ljo.left != nil || ljo.node != nil {
@@ -437,7 +437,7 @@ func newJoinOrderNode(node sql.Node) *joinOrderNode {
437437
if rjo.left != nil || rjo.node != nil {
438438
commutes = append(commutes, *rjo)
439439
}
440-
return &joinOrderNode{commutes: commutes}
440+
return &joinOrderNode{commutes: commutes}, lcnt + rcnt
441441
}
442442
default:
443443
panic(fmt.Sprintf("unexpected node type: %t", node))

sql/analyzer/rules.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ var OnceBeforeDefault = []Rule{
5757
{validateDatabaseSetId, validateDatabaseSet},
5858
{validatePriviledgesId, validatePrivileges}, // Ensure that checking privileges happens after db, table & table function resolution
5959
{stripDecorationsId, stripDecorations},
60-
{validateJoinComplexityId, validateJoinComplexity},
6160
}
6261

6362
// DefaultRules to apply when analyzing nodes.

0 commit comments

Comments
 (0)