Skip to content

Commit

Permalink
planner: refactor the cost implementation for PointGet/BatchGet (ping…
Browse files Browse the repository at this point in the history
  • Loading branch information
qw4990 authored Apr 28, 2022
1 parent 42089cd commit 0fbdb6c
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 17 deletions.
20 changes: 12 additions & 8 deletions planner/core/find_best_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -1964,7 +1964,8 @@ func (ds *DataSource) convertToPointGet(prop *property.PhysicalProperty, candida
pointGetPlan.Handle = kv.IntHandle(candidate.path.Ranges[0].LowVal[0].GetInt64())
pointGetPlan.UnsignedHandle = mysql.HasUnsignedFlag(ds.handleCols.GetCol(0).RetType.GetFlag())
pointGetPlan.PartitionInfo = partitionInfo
cost = pointGetPlan.GetCost(ds.TblCols)
pointGetPlan.accessCols = ds.TblCols
cost = pointGetPlan.GetCost()
// Add filter condition to table plan now.
if len(candidate.path.TableFilters) > 0 {
sessVars := ds.ctx.GetSessionVars()
Expand All @@ -1982,10 +1983,11 @@ func (ds *DataSource) convertToPointGet(prop *property.PhysicalProperty, candida
pointGetPlan.IndexValues = candidate.path.Ranges[0].LowVal
pointGetPlan.PartitionInfo = partitionInfo
if candidate.path.IsSingleScan {
cost = pointGetPlan.GetCost(candidate.path.IdxCols)
pointGetPlan.accessCols = candidate.path.IdxCols
} else {
cost = pointGetPlan.GetCost(ds.TblCols)
pointGetPlan.accessCols = ds.TblCols
}
cost = pointGetPlan.GetCost()
// Add index condition to table plan now.
if len(candidate.path.IndexFilters)+len(candidate.path.TableFilters) > 0 {
sessVars := ds.ctx.GetSessionVars()
Expand All @@ -1999,7 +2001,7 @@ func (ds *DataSource) convertToPointGet(prop *property.PhysicalProperty, candida
}

rTsk.cst = cost
pointGetPlan.SetCost(cost)
rTsk.p.SetCost(cost)
return rTsk
}

Expand Down Expand Up @@ -2033,7 +2035,8 @@ func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty,
for _, ran := range candidate.path.Ranges {
batchPointGetPlan.Handles = append(batchPointGetPlan.Handles, kv.IntHandle(ran.LowVal[0].GetInt64()))
}
cost = batchPointGetPlan.GetCost(ds.TblCols)
batchPointGetPlan.accessCols = ds.TblCols
cost = batchPointGetPlan.GetCost()
// Add filter condition to table plan now.
if len(candidate.path.TableFilters) > 0 {
sessVars := ds.ctx.GetSessionVars()
Expand All @@ -2057,10 +2060,11 @@ func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty,
batchPointGetPlan.Desc = prop.SortItems[0].Desc
}
if candidate.path.IsSingleScan {
cost = batchPointGetPlan.GetCost(candidate.path.IdxCols)
batchPointGetPlan.accessCols = candidate.path.IdxCols
} else {
cost = batchPointGetPlan.GetCost(ds.TblCols)
batchPointGetPlan.accessCols = ds.TblCols
}
cost = batchPointGetPlan.GetCost()
// Add index condition to table plan now.
if len(candidate.path.IndexFilters)+len(candidate.path.TableFilters) > 0 {
sessVars := ds.ctx.GetSessionVars()
Expand All @@ -2074,7 +2078,7 @@ func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty,
}

rTsk.cst = cost
batchPointGetPlan.SetCost(cost)
rTsk.p.SetCost(cost)
return rTsk
}

Expand Down
14 changes: 12 additions & 2 deletions planner/core/plan_cost.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,12 +349,22 @@ func (p *PhysicalTopN) GetPlanCost(taskType property.TaskType) (float64, error)

// GetPlanCost calculates the cost of the plan if it has not been calculated yet and returns the cost.
func (p *BatchPointGetPlan) GetPlanCost(taskType property.TaskType) (float64, error) {
return 0, errors.New("not implemented")
if p.planCostInit {
return p.planCost, nil
}
p.planCost = p.GetCost()
p.planCostInit = true
return p.planCost, nil
}

// GetPlanCost calculates the cost of the plan if it has not been calculated yet and returns the cost.
func (p *PointGetPlan) GetPlanCost(taskType property.TaskType) (float64, error) {
return 0, errors.New("not implemented")
if p.planCostInit {
return p.planCost, nil
}
p.planCost = p.GetCost()
p.planCostInit = true
return p.planCost, nil
}

// GetPlanCost calculates the cost of the plan if it has not been calculated yet and returns the cost.
Expand Down
11 changes: 10 additions & 1 deletion planner/core/plan_cost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TestNewCostInterfaceTiKV(t *testing.T) {
tk := testkit.NewTestKit(t, store)

tk.MustExec("use test")
tk.MustExec(`create table t (a int primary key, b int, c int, d int, key b(b), key cd(c, d))`)
tk.MustExec(`create table t (a int primary key, b int, c int, d int, k int, key b(b), key cd(c, d), unique key(k))`)

queries := []string{
// table-reader
Expand Down Expand Up @@ -193,6 +193,15 @@ func TestNewCostInterfaceTiKV(t *testing.T) {
"select * from t use index(cd) where c < 200 order by c limit 10",
"select * from t use index(cd) where c = 200 order by c limit 10",
"select * from t use index(cd) where c = 200 and d < 200 order by c, d limit 10",
// point get
"select * from t where a = 1", // generated in fast plan optimization
"select * from t where a in (1, 2, 3, 4, 5)",
"select * from t where k = 1",
"select * from t where k in (1, 2, 3, 4, 5)",
"select * from t where a=1 and mod(a, b)=2", // generated in physical plan optimization
"select * from t where a in (1, 2, 3, 4, 5) and mod(a, b)=2",
"select * from t where k=1 and mod(k, b)=2",
"select * from t where k in (1, 2, 3, 4, 5) and mod(k, b)=2",
// union all
"select * from t use index(primary) union all select * from t use index(primary) where a < 200",
"select b from t use index(primary) union all select b from t use index(b) where b < 200",
Expand Down
24 changes: 22 additions & 2 deletions planner/core/point_get_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ type PointGetPlan struct {
partitionColumnPos int
Columns []*model.ColumnInfo
cost float64

// required by cost model
planCostInit bool
planCost float64
// accessCols represents actual columns the PointGet will access, which are used to calculate row-size
accessCols []*expression.Column
}

type nameValuePair struct {
Expand Down Expand Up @@ -256,7 +262,11 @@ func (p *PointGetPlan) SetOutputNames(names types.NameSlice) {
}

// GetCost returns cost of the PointGetPlan.
func (p *PointGetPlan) GetCost(cols []*expression.Column) float64 {
func (p *PointGetPlan) GetCost() float64 {
cols := p.accessCols
if cols == nil {
return 0 // the cost of PointGet generated in fast plan optimization is always 0
}
sessVars := p.ctx.GetSessionVars()
var rowSize float64
cost := 0.0
Expand Down Expand Up @@ -305,6 +315,12 @@ type BatchPointGetPlan struct {
SinglePart bool
// PartTblID is the table ID for the specific table partition.
PartTblID int64

// required by cost model
planCostInit bool
planCost float64
// accessCols represents actual columns the PointGet will access, which are used to calculate row-size
accessCols []*expression.Column
}

// Cost implements PhysicalPlan interface
Expand Down Expand Up @@ -444,7 +460,11 @@ func (p *BatchPointGetPlan) SetOutputNames(names types.NameSlice) {
}

// GetCost returns cost of the PointGetPlan.
func (p *BatchPointGetPlan) GetCost(cols []*expression.Column) float64 {
func (p *BatchPointGetPlan) GetCost() float64 {
cols := p.accessCols
if cols == nil {
return 0 // the cost of BatchGet generated in fast plan optimization is always 0
}
sessVars := p.ctx.GetSessionVars()
var rowSize, rowCount float64
cost := 0.0
Expand Down
8 changes: 4 additions & 4 deletions planner/core/testdata/integration_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -1723,8 +1723,8 @@
{
"SQL": "select a, b, c from t2 where a = 1 and b = 2 and c in (1, 2, 3, 4, 5)",
"Plan": [
"Selection_6 0.01 0.00 root eq(test.t2.b, 2), in(test.t2.c, 1, 2, 3, 4, 5)",
"└─Point_Get_5 1.00 8.60 root table:t2, index:idx_a(a) "
"Selection_6 0.01 8.60 root eq(test.t2.b, 2), in(test.t2.c, 1, 2, 3, 4, 5)",
"└─Point_Get_5 1.00 0.00 root table:t2, index:idx_a(a) "
],
"Warnings": [
"Note 1105 unique index idx_a of t2 is selected since the path only has point ranges with double scan"
Expand Down Expand Up @@ -1780,8 +1780,8 @@
"SQL": "delete from t1 where f = 2 and g in (3, 4)",
"Plan": [
"Delete_4 N/A N/A root N/A",
"└─Selection_7 2.00 0.00 root in(test.t1.g, 3, 4)",
" └─Point_Get_6 1.00 9.80 root table:t1, index:f(f) "
"└─Selection_7 2.00 9.80 root in(test.t1.g, 3, 4)",
" └─Point_Get_6 1.00 0.00 root table:t1, index:f(f) "
],
"Warnings": [
"Note 1105 unique index f of t1 is selected since the path only has point ranges with double scan"
Expand Down

0 comments on commit 0fbdb6c

Please sign in to comment.