Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Planner refactoring #7103

Merged
merged 42 commits into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a924e24
Semantic analysis
systay Dec 21, 2020
7f4c826
Added tests for query graph
GuptaManan100 Dec 22, 2020
ed8cfe7
Added 2nd planner test capability to plan_test
GuptaManan100 Dec 22, 2020
13095ef
Test New Planner
systay Dec 22, 2020
91c8c95
added the first two succesful new planner tests
systay Dec 22, 2020
bdf65b2
checked all the tests that work with the 2nd planner
GuptaManan100 Dec 22, 2020
8a148e7
support more cases with the new planner
systay Dec 22, 2020
09a6dac
new planner can solve the simplest join plans
systay Dec 22, 2020
9691541
remove randomness from the planbuilding process
systay Dec 22, 2020
713ea58
fix issue with the dp table
systay Dec 23, 2020
44de903
add greedy option for large queries
systay Dec 23, 2020
14f4680
refactor: extract method
systay Dec 27, 2020
9224b3a
refactor: querygraph and test
systay Dec 27, 2020
9aa2331
moved code to where it belongs
systay Dec 27, 2020
e500d3a
simplify routePlan
systay Dec 28, 2020
63d4339
added route planning unit tests
systay Dec 28, 2020
b1a5df8
added flag to control the planner version
systay Dec 28, 2020
4ecd166
added left to right planner
systay Dec 28, 2020
33f5ca5
add planner benchmark
harshit-gangal Dec 29, 2020
74e6d7e
Supported merging joins in selectScatter queries
GuptaManan100 Dec 29, 2020
4613d6c
pushed predicates to the correct place in join queries
GuptaManan100 Dec 29, 2020
c7aecd3
added vtgate flag and system variable to control the planner used
systay Dec 29, 2020
b4ac6de
added helpful comments
systay Dec 29, 2020
cf1ad11
add a shortcut to the greedy planner to prefer joins with predicates
systay Dec 29, 2020
000426e
change planner benchmark to only read the input file once
systay Dec 29, 2020
1c9c5eb
added a new version of greedy optimizer using priority queue
GuptaManan100 Dec 30, 2020
9c16d63
fixed join predicate collection issue
GuptaManan100 Dec 30, 2020
23d6535
added more supported queries
systay Dec 30, 2020
57e14ca
handle null comparisons in the V4 planner
systay Dec 30, 2020
4b83703
fail plan tests if the v4 planner unexpectedly produces the same plan…
systay Dec 30, 2020
b9fa57e
merge SelectEqualUnique plans
systay Jan 1, 2021
ecd4936
refactored route planning code
systay Jan 1, 2021
3bafc10
Remove the assumption that A join B has the same cost as B join A
systay Jan 1, 2021
2d4dd72
don't copy table qualifier and only copy some fields if the full plan…
systay Jan 2, 2021
ff4adae
keep tables in FROM according to original query
systay Jan 2, 2021
7f3c956
Merge remote-tracking branch 'upstream/master' into horizon-planning
systay Jan 7, 2021
027e154
fix lint on go/vt/srvtopo/resilient_server_test.go
shlomi-noach Jan 7, 2021
01a1ef1
imports
systay Jan 7, 2021
5dc6497
cleaned out code
systay Jan 7, 2021
d285bfe
removed planner-version sysvar
systay Jan 11, 2021
26b008b
adress peer review comments
systay Jan 11, 2021
35e41cd
Merge remote-tracking branch 'upstream/master' into horizon-planning
systay Jan 11, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
456 changes: 253 additions & 203 deletions go/vt/proto/query/query.pb.go

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions go/vt/sqlparser/ast_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,14 @@ func (lock LockOptionType) ToString() string {
}
}

// CompliantName is used to get the name of the bind variable to use for this column name
func (node *ColName) CompliantName(suffix string) string {
if !node.Qualifier.IsEmpty() {
return node.Qualifier.Name.CompliantName() + "_" + node.Name.CompliantName() + suffix
}
return node.Name.CompliantName() + suffix
}

// AtCount represents the '@' count in ColIdent
type AtCount int

Expand Down
6 changes: 4 additions & 2 deletions go/vt/srvtopo/resilient_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ func TestGetSrvKeyspace(t *testing.T) {

time.Sleep(*srvTopoCacheTTL)

timeoutCtx, _ := context.WithTimeout(context.Background(), *srvTopoCacheRefresh*2) //nolint
timeoutCtx, cancel := context.WithTimeout(context.Background(), *srvTopoCacheRefresh*2) //nolint
defer cancel()
_, err = rs.GetSrvKeyspace(timeoutCtx, "test_cell", "test_ks")
wantErr := "timed out waiting for keyspace"
if err == nil || err.Error() != wantErr {
Expand Down Expand Up @@ -614,7 +615,8 @@ func TestGetSrvKeyspaceNames(t *testing.T) {

time.Sleep(*srvTopoCacheTTL)

timeoutCtx, _ := context.WithTimeout(context.Background(), *srvTopoCacheRefresh*2) //nolint
timeoutCtx, cancel := context.WithTimeout(context.Background(), *srvTopoCacheRefresh*2) //nolint
defer cancel()
_, err = rs.GetSrvKeyspaceNames(timeoutCtx, "test_cell", false)
wantErr := "timed out waiting for keyspace names"
if err == nil || err.Error() != wantErr {
Expand Down
8 changes: 8 additions & 0 deletions go/vt/vtgate/engine/fake_vcursor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ func (t noopVCursor) SetWorkload(querypb.ExecuteOptions_Workload) {
panic("implement me")
}

func (t noopVCursor) SetPlannerVersion(querypb.ExecuteOptions_PlannerVersion) {
panic("implement me")
}

func (t noopVCursor) SetTarget(string) error {
panic("implement me")
}
Expand Down Expand Up @@ -483,6 +487,10 @@ func (f *loggingVCursor) SetWorkload(querypb.ExecuteOptions_Workload) {
panic("implement me")
}

func (f *loggingVCursor) SetPlannerVersion(querypb.ExecuteOptions_PlannerVersion) {
panic("implement me")
}

func (f *loggingVCursor) FindRoutedTable(tbl sqlparser.TableName) (*vindexes.Table, error) {
f.log = append(f.log, fmt.Sprintf("FindTable(%s)", sqlparser.String(tbl)))
return f.tableRoutes.tbl, nil
Expand Down
1 change: 1 addition & 0 deletions go/vt/vtgate/engine/primitive.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ type (
SetSQLSelectLimit(int64) error
SetTransactionMode(vtgatepb.TransactionMode)
SetWorkload(querypb.ExecuteOptions_Workload)
SetPlannerVersion(querypb.ExecuteOptions_PlannerVersion)
SetFoundRows(uint64)

SetDDLStrategy(string)
Expand Down
1 change: 0 additions & 1 deletion go/vt/vtgate/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ type Executor struct {
var executorOnce sync.Once

const pathQueryPlans = "/debug/query_plans"

const pathScatterStats = "/debug/scatter_stats"
const pathVSchema = "/debug/vschema"

Expand Down
17 changes: 17 additions & 0 deletions go/vt/vtgate/planbuilder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"vitess.io/vitess/go/sqltypes"
querypb "vitess.io/vitess/go/vt/proto/query"
"vitess.io/vitess/go/vt/vtgate/semantics"

"vitess.io/vitess/go/vt/vterrors"

Expand Down Expand Up @@ -49,8 +50,24 @@ type ContextVSchema interface {
SysVarSetEnabled() bool
KeyspaceExists(keyspace string) bool
AllKeyspace() ([]*vindexes.Keyspace, error)
GetSemTable() *semantics.SemTable
Planner() PlannerVersion
}

// PlannerVersion is an alias here to make the code more readable
type PlannerVersion = querypb.ExecuteOptions_PlannerVersion

const (
// V3 is also the default planner
V3 = querypb.ExecuteOptions_V3
// V4 uses the default V4 planner, which is the greedy planner
V4 = querypb.ExecuteOptions_V4
// V4GreedyOnly uses only the faster greedy planner
V4GreedyOnly = querypb.ExecuteOptions_V4Greedy
// V4Left2Right tries to emulate the V3 planner by only joining plans in the order they are listed in the FROM-clause
V4Left2Right = querypb.ExecuteOptions_V4Left2Right
)

type truncater interface {
SetTruncateColumnCount(int)
}
Expand Down
13 changes: 13 additions & 0 deletions go/vt/vtgate/planbuilder/concatenate.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/vterrors"
"vitess.io/vitess/go/vt/vtgate/engine"
"vitess.io/vitess/go/vt/vtgate/semantics"
)

type concatenate struct {
Expand Down Expand Up @@ -53,6 +54,14 @@ func (c *concatenate) Wireup(plan logicalPlan, jt *jointab) error {
return c.rhs.Wireup(plan, jt)
}

func (c *concatenate) WireupV4(semTable *semantics.SemTable) error {
err := c.lhs.WireupV4(semTable)
if err != nil {
return err
}
return c.rhs.WireupV4(semTable)
}

func (c *concatenate) SupplyVar(from, to int, col *sqlparser.ColName, varname string) {
panic("implement me")
}
Expand Down Expand Up @@ -84,6 +93,10 @@ func (c *concatenate) Rewrite(inputs ...logicalPlan) error {
return nil
}

func (c *concatenate) ContainsTables() semantics.TableSet {
return c.lhs.ContainsTables().Merge(c.rhs.ContainsTables())
}

// Inputs implements the logicalPlan interface
func (c *concatenate) Inputs() []logicalPlan {
return []logicalPlan{c.lhs, c.rhs}
Expand Down
16 changes: 16 additions & 0 deletions go/vt/vtgate/planbuilder/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package planbuilder
import (
"errors"

"vitess.io/vitess/go/vt/vtgate/semantics"

vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
"vitess.io/vitess/go/vt/vterrors"

Expand Down Expand Up @@ -151,6 +153,15 @@ func (jb *join) Wireup(plan logicalPlan, jt *jointab) error {
return jb.Left.Wireup(plan, jt)
}

// Wireup2 implements the logicalPlan interface
func (jb *join) WireupV4(semTable *semantics.SemTable) error {
err := jb.Right.WireupV4(semTable)
if err != nil {
return err
}
return jb.Left.WireupV4(semTable)
}

// SupplyVar implements the logicalPlan interface
func (jb *join) SupplyVar(from, to int, col *sqlparser.ColName, varname string) {
if !jb.isOnLeft(from) {
Expand Down Expand Up @@ -235,6 +246,11 @@ func (jb *join) Rewrite(inputs ...logicalPlan) error {
return nil
}

// Solves implements the logicalPlan interface
func (jb *join) ContainsTables() semantics.TableSet {
return jb.Left.ContainsTables().Merge(jb.Right.ContainsTables())
}

// Inputs implements the logicalPlan interface
func (jb *join) Inputs() []logicalPlan {
return []logicalPlan{jb.Left, jb.Right}
Expand Down
103 changes: 103 additions & 0 deletions go/vt/vtgate/planbuilder/join2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
Copyright 2019 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package planbuilder

import (
"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/vtgate/engine"
"vitess.io/vitess/go/vt/vtgate/semantics"
)

var _ logicalPlan = (*joinV4)(nil)

// joinV4 is used to build a Join primitive.
// It's used to build an inner join and only used by the V4 planner
type joinV4 struct {
// Left and Right are the nodes for the join.
Left, Right logicalPlan
Cols []int
Vars map[string]int
}

// Order implements the logicalPlan interface
func (j *joinV4) Order() int {
panic("implement me")
}

// ResultColumns implements the logicalPlan interface
func (j *joinV4) ResultColumns() []*resultColumn {
panic("implement me")
}

// Reorder implements the logicalPlan interface
func (j *joinV4) Reorder(i int) {
panic("implement me")
}

// Wireup implements the logicalPlan interface
func (j *joinV4) Wireup(lp logicalPlan, jt *jointab) error {
panic("implement me")
}

// Wireup2 implements the logicalPlan interface
func (j *joinV4) WireupV4(semTable *semantics.SemTable) error {
err := j.Left.WireupV4(semTable)
if err != nil {
return err
}
return j.Right.WireupV4(semTable)
}

// SupplyVar implements the logicalPlan interface
func (j *joinV4) SupplyVar(from, to int, col *sqlparser.ColName, varname string) {
panic("implement me")
}

// SupplyCol implements the logicalPlan interface
func (j *joinV4) SupplyCol(col *sqlparser.ColName) (rc *resultColumn, colNumber int) {
panic("implement me")
}

// SupplyWeightString implements the logicalPlan interface
func (j *joinV4) SupplyWeightString(colNumber int) (weightcolNumber int, err error) {
panic("implement me")
}

// Primitive implements the logicalPlan interface
func (j *joinV4) Primitive() engine.Primitive {
return &engine.Join{
Left: j.Left.Primitive(),
Right: j.Right.Primitive(),
Cols: j.Cols,
Vars: j.Vars,
}
}

// Inputs implements the logicalPlan interface
func (j *joinV4) Inputs() []logicalPlan {
panic("implement me")
}

// Rewrite implements the logicalPlan interface
func (j *joinV4) Rewrite(inputs ...logicalPlan) error {
panic("implement me")
}

// Solves implements the logicalPlan interface
func (j *joinV4) ContainsTables() semantics.TableSet {
return j.Left.ContainsTables().Merge(j.Right.ContainsTables())
}
6 changes: 1 addition & 5 deletions go/vt/vtgate/planbuilder/jointab.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,7 @@ func (jt *jointab) Procure(plan logicalPlan, col *sqlparser.ColName, to int) str
suffix := ""
i := 0
for {
if !col.Qualifier.IsEmpty() {
joinVar = col.Qualifier.Name.CompliantName() + "_" + col.Name.CompliantName() + suffix
} else {
joinVar = col.Name.CompliantName() + suffix
}
joinVar = col.CompliantName(suffix)
if _, ok := jt.vars[joinVar]; !ok {
break
}
Expand Down
20 changes: 20 additions & 0 deletions go/vt/vtgate/planbuilder/logical_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/vterrors"
"vitess.io/vitess/go/vt/vtgate/engine"
"vitess.io/vitess/go/vt/vtgate/semantics"
)

// logicalPlan defines the interface that a primitive must
Expand Down Expand Up @@ -48,6 +49,9 @@ type logicalPlan interface {
// the lhs nodes.
Wireup(lp logicalPlan, jt *jointab) error

// WireupV4 does the wire up work for the V4 planner
WireupV4(semTable *semantics.SemTable) error

// SupplyVar finds the common root between from and to. If it's
// the common root, it supplies the requested var to the rhs tree.
// If the primitive already has the column in its list, it should
Expand All @@ -72,8 +76,15 @@ type logicalPlan interface {
// This function should only be called after Wireup is finished.
Primitive() engine.Primitive

// Inputs are the children of this plan
Inputs() []logicalPlan

// Rewrite replaces the inputs of this plan with the ones provided
Rewrite(inputs ...logicalPlan) error

// ContainsTables keeps track which query tables are being solved by this logical plan
// This is only applicable for plans that have been built with the V4 planner
ContainsTables() semantics.TableSet
}

//-------------------------------------------------------------------------
Expand Down Expand Up @@ -147,6 +158,10 @@ func (bc *logicalPlanCommon) Wireup(plan logicalPlan, jt *jointab) error {
return bc.input.Wireup(plan, jt)
}

func (bc *logicalPlanCommon) WireupV4(semTable *semantics.SemTable) error {
return bc.input.WireupV4(semTable)
}

func (bc *logicalPlanCommon) SupplyVar(from, to int, col *sqlparser.ColName, varname string) {
bc.input.SupplyVar(from, to, col, varname)
}
Expand All @@ -173,6 +188,11 @@ func (bc *logicalPlanCommon) Inputs() []logicalPlan {
return []logicalPlan{bc.input}
}

// Solves implements the logicalPlan interface
func (bc *logicalPlanCommon) ContainsTables() semantics.TableSet {
return bc.input.ContainsTables()
}

//-------------------------------------------------------------------------

// resultsBuilder is a superset of logicalPlanCommon. It also handles
Expand Down
6 changes: 6 additions & 0 deletions go/vt/vtgate/planbuilder/memory_sort.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"errors"
"fmt"

"vitess.io/vitess/go/vt/vtgate/semantics"

"vitess.io/vitess/go/sqltypes"
"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/vtgate/engine"
Expand Down Expand Up @@ -125,3 +127,7 @@ func (ms *memorySort) Wireup(plan logicalPlan, jt *jointab) error {
}
return ms.input.Wireup(plan, jt)
}

func (ms *memorySort) WireupV4(semTable *semantics.SemTable) error {
return ms.input.WireupV4(semTable)
}
5 changes: 5 additions & 0 deletions go/vt/vtgate/planbuilder/merge_sort.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package planbuilder
import (
"vitess.io/vitess/go/sqltypes"
"vitess.io/vitess/go/vt/vtgate/engine"
"vitess.io/vitess/go/vt/vtgate/semantics"
)

var _ logicalPlan = (*mergeSort)(nil)
Expand Down Expand Up @@ -82,3 +83,7 @@ func (ms *mergeSort) Wireup(plan logicalPlan, jt *jointab) error {
rb.eroute.TruncateColumnCount = ms.truncateColumnCount
return ms.input.Wireup(plan, jt)
}

func (ms *mergeSort) WireupV4(semTable *semantics.SemTable) error {
return ms.input.WireupV4(semTable)
}
Loading