Skip to content

Commit

Permalink
planner: move cost factors to core/cost pkg (#53120)
Browse files Browse the repository at this point in the history
ref #51664, ref #52714
  • Loading branch information
AilinKid authored May 9, 2024
1 parent 11ccc2e commit f0a7447
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 78 deletions.
1 change: 1 addition & 0 deletions pkg/planner/core/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ go_library(
"//pkg/planner/cardinality",
"//pkg/planner/context",
"//pkg/planner/core/base",
"//pkg/planner/core/cost",
"//pkg/planner/core/metrics",
"//pkg/planner/core/operator/baseimpl",
"//pkg/planner/funcdep",
Expand Down
9 changes: 9 additions & 0 deletions pkg/planner/core/cost/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "cost",
srcs = ["factors_thresholds.go"],
importpath = "github.com/pingcap/tidb/pkg/planner/core/cost",
visibility = ["//visibility:public"],
deps = ["//pkg/parser/ast"],
)
54 changes: 54 additions & 0 deletions pkg/planner/core/cost/factors_thresholds.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2024 PingCAP, Inc.
//
// 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 cost

import "github.com/pingcap/tidb/pkg/parser/ast"

// ******************************* Factors *******************************
const (
// SelectionFactor is the default factor of the selectivity.
// For example, If we have no idea how to estimate the selectivity
// of a Selection or a JoinCondition, we can use this default value.
SelectionFactor = 0.8

DistinctFactor = 0.8
)

// AggFuncFactor is the basic factor for aggregation.
var AggFuncFactor = map[string]float64{
ast.AggFuncCount: 1.0,
ast.AggFuncSum: 1.0,
ast.AggFuncAvg: 2.0,
ast.AggFuncFirstRow: 0.1,
ast.AggFuncMax: 1.0,
ast.AggFuncMin: 1.0,
ast.AggFuncGroupConcat: 1.0,
ast.AggFuncBitOr: 0.9,
ast.AggFuncBitXor: 0.9,
ast.AggFuncBitAnd: 0.9,
ast.AggFuncVarPop: 3.0,
ast.AggFuncVarSamp: 3.0,
ast.AggFuncStddevPop: 3.0,
ast.AggFuncStddevSamp: 3.0,
"default": 1.5,
}

// // ******************************* Thresholds *******************************
const (
// SmallScanThreshold means: If the actual row count is much more
// than the limit count, the unordered scan may cost much more than keep order.
// So when a limit exists, we don't apply the DescScanFactor.
SmallScanThreshold = 10000
)
7 changes: 4 additions & 3 deletions pkg/planner/core/exhaust_physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/pingcap/tidb/pkg/parser/mysql"
"github.com/pingcap/tidb/pkg/planner/cardinality"
"github.com/pingcap/tidb/pkg/planner/core/base"
"github.com/pingcap/tidb/pkg/planner/core/cost"
"github.com/pingcap/tidb/pkg/planner/property"
"github.com/pingcap/tidb/pkg/planner/util"
"github.com/pingcap/tidb/pkg/planner/util/fixcontrol"
Expand Down Expand Up @@ -1078,7 +1079,7 @@ func (p *LogicalJoin) constructInnerTableScanTask(
selectivity, _, err = cardinality.Selectivity(ds.SCtx(), ds.tableStats.HistColl, ts.filterCondition, ds.possibleAccessPaths)
if err != nil || selectivity <= 0 {
logutil.BgLogger().Debug("unexpected selectivity, use selection factor", zap.Float64("selectivity", selectivity), zap.String("table", ts.TableAsName.L))
selectivity = SelectionFactor
selectivity = cost.SelectionFactor
}
// rowCount is computed from result row count of join, which has already accounted the filters on DataSource,
// i.e, rowCount equals to `countAfterAccess * selectivity`.
Expand Down Expand Up @@ -1370,7 +1371,7 @@ func (p *LogicalJoin) constructInnerIndexScanTask(
selectivity, _, err := cardinality.Selectivity(ds.SCtx(), ds.tableStats.HistColl, tblConds, ds.possibleAccessPaths)
if err != nil || selectivity <= 0 {
logutil.BgLogger().Debug("unexpected selectivity, use selection factor", zap.Float64("selectivity", selectivity), zap.String("table", ds.TableAsName.L))
selectivity = SelectionFactor
selectivity = cost.SelectionFactor
}
// rowCount is computed from result row count of join, which has already accounted the filters on DataSource,
// i.e, rowCount equals to `countAfterIndex * selectivity`.
Expand All @@ -1388,7 +1389,7 @@ func (p *LogicalJoin) constructInnerIndexScanTask(
selectivity, _, err := cardinality.Selectivity(ds.SCtx(), ds.tableStats.HistColl, indexConds, ds.possibleAccessPaths)
if err != nil || selectivity <= 0 {
logutil.BgLogger().Debug("unexpected selectivity, use selection factor", zap.Float64("selectivity", selectivity), zap.String("table", ds.TableAsName.L))
selectivity = SelectionFactor
selectivity = cost.SelectionFactor
}
cnt := tmpPath.CountAfterIndex / selectivity
if rowCountUpperBound > 0 {
Expand Down
41 changes: 6 additions & 35 deletions pkg/planner/core/find_best_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/pingcap/tidb/pkg/parser/mysql"
"github.com/pingcap/tidb/pkg/planner/cardinality"
"github.com/pingcap/tidb/pkg/planner/core/base"
"github.com/pingcap/tidb/pkg/planner/core/cost"
"github.com/pingcap/tidb/pkg/planner/property"
"github.com/pingcap/tidb/pkg/planner/util"
"github.com/pingcap/tidb/pkg/planner/util/fixcontrol"
Expand All @@ -47,36 +48,6 @@ import (
"go.uber.org/zap"
)

const (
// SelectionFactor is the default factor of the selectivity.
// For example, If we have no idea how to estimate the selectivity
// of a Selection or a JoinCondition, we can use this default value.
SelectionFactor = 0.8
distinctFactor = 0.8

// If the actual row count is much more than the limit count, the unordered scan may cost much more than keep order.
// So when a limit exists, we don't apply the DescScanFactor.
smallScanThreshold = 10000
)

var aggFuncFactor = map[string]float64{
ast.AggFuncCount: 1.0,
ast.AggFuncSum: 1.0,
ast.AggFuncAvg: 2.0,
ast.AggFuncFirstRow: 0.1,
ast.AggFuncMax: 1.0,
ast.AggFuncMin: 1.0,
ast.AggFuncGroupConcat: 1.0,
ast.AggFuncBitOr: 0.9,
ast.AggFuncBitXor: 0.9,
ast.AggFuncBitAnd: 0.9,
ast.AggFuncVarPop: 3.0,
ast.AggFuncVarSamp: 3.0,
ast.AggFuncStddevPop: 3.0,
ast.AggFuncStddevSamp: 3.0,
"default": 1.5,
}

// PlanCounterDisabled is the default value of PlanCounterTp, indicating that optimizer needn't force a plan.
var PlanCounterDisabled base.PlanCounterTp = -1

Expand Down Expand Up @@ -1042,7 +1013,7 @@ func (ds *DataSource) matchPropForIndexMergeAlternatives(path *util.AccessPath,
sel, _, err := cardinality.Selectivity(ds.SCtx(), ds.tableStats.HistColl, []expression.Expression{accessDNF}, nil)
if err != nil {
logutil.BgLogger().Debug("something wrong happened, use the default selectivity", zap.Error(err))
sel = SelectionFactor
sel = cost.SelectionFactor
}
indexMergePath.CountAfterAccess = sel * ds.tableStats.RowCount
if noSortItem {
Expand Down Expand Up @@ -1730,7 +1701,7 @@ func (ds *DataSource) convertToPartialTableScan(prop *property.PhysicalProperty,
selectivity, _, err := cardinality.Selectivity(ds.SCtx(), ds.tableStats.HistColl, ts.filterCondition, nil)
if err != nil {
logutil.BgLogger().Debug("calculate selectivity failed, use selection factor", zap.Error(err))
selectivity = SelectionFactor
selectivity = cost.SelectionFactor
}
tablePlan = PhysicalSelection{Conditions: ts.filterCondition}.Init(ts.SCtx(), ts.StatsInfo().ScaleByExpectCnt(selectivity*rowCount), ds.QueryBlockOffset())
tablePlan.SetChildren(ts)
Expand Down Expand Up @@ -1816,7 +1787,7 @@ func (ds *DataSource) buildIndexMergeTableScan(tableFilters []expression.Express
selectivity, _, err := cardinality.Selectivity(ds.SCtx(), ds.tableStats.HistColl, pushedFilters, nil)
if err != nil {
logutil.BgLogger().Debug("calculate selectivity failed, use selection factor", zap.Error(err))
selectivity = SelectionFactor
selectivity = cost.SelectionFactor
}
sel := PhysicalSelection{Conditions: pushedFilters}.Init(ts.SCtx(), ts.StatsInfo().ScaleByExpectCnt(selectivity*totalRowCount), ts.QueryBlockOffset())
sel.SetChildren(ts)
Expand Down Expand Up @@ -2299,7 +2270,7 @@ func (is *PhysicalIndexScan) addPushedDownSelection(copTask *CopTask, p *DataSou
selectivity, _, err := cardinality.Selectivity(is.SCtx(), copTask.tblColHists, tableConds, nil)
if err != nil {
logutil.BgLogger().Debug("calculate selectivity failed, use selection factor", zap.Error(err))
selectivity = SelectionFactor
selectivity = cost.SelectionFactor
}
tableSel.SetStats(copTask.Plan().StatsInfo().Scale(selectivity))
}
Expand Down Expand Up @@ -2790,7 +2761,7 @@ func (ts *PhysicalTableScan) addPushedDownSelection(copTask *CopTask, stats *pro
selectivity, _, err := cardinality.Selectivity(ts.SCtx(), copTask.tblColHists, ts.filterCondition, nil)
if err != nil {
logutil.BgLogger().Debug("calculate selectivity failed, use selection factor", zap.Error(err))
selectivity = SelectionFactor
selectivity = cost.SelectionFactor
}
sel.SetStats(ts.StatsInfo().Scale(selectivity))
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/planner/core/indexmerge_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/pingcap/tidb/pkg/planner/cardinality"
"github.com/pingcap/tidb/pkg/planner/context"
"github.com/pingcap/tidb/pkg/planner/core/base"
"github.com/pingcap/tidb/pkg/planner/core/cost"
"github.com/pingcap/tidb/pkg/planner/util"
"github.com/pingcap/tidb/pkg/planner/util/debugtrace"
"github.com/pingcap/tidb/pkg/planner/util/fixcontrol"
Expand Down Expand Up @@ -286,7 +287,7 @@ func (ds *DataSource) generateIndexMergeOrPaths(filters []expression.Expression)
sel, _, err := cardinality.Selectivity(ds.SCtx(), ds.tableStats.HistColl, []expression.Expression{accessDNF}, nil)
if err != nil {
logutil.BgLogger().Debug("something wrong happened, use the default selectivity", zap.Error(err))
sel = SelectionFactor
sel = cost.SelectionFactor
}

possiblePath := buildIndexMergeOrPath(filters, partialAlternativePaths, k, shouldKeepCurrentFilter)
Expand Down Expand Up @@ -594,7 +595,7 @@ func (ds *DataSource) generateIndexMergeAndPaths(normalPathCnt int, usedAccessMa
sel, _, err := cardinality.Selectivity(ds.SCtx(), ds.tableStats.HistColl, partialFilters, nil)
if err != nil {
logutil.BgLogger().Debug("something wrong happened, use the default selectivity", zap.Error(err))
sel = SelectionFactor
sel = cost.SelectionFactor
}

indexMergePath := &util.AccessPath{
Expand Down
9 changes: 5 additions & 4 deletions pkg/planner/core/logical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/pingcap/tidb/pkg/parser/mysql"
"github.com/pingcap/tidb/pkg/planner/cardinality"
"github.com/pingcap/tidb/pkg/planner/core/base"
"github.com/pingcap/tidb/pkg/planner/core/cost"
fd "github.com/pingcap/tidb/pkg/planner/funcdep"
"github.com/pingcap/tidb/pkg/planner/property"
"github.com/pingcap/tidb/pkg/planner/util"
Expand Down Expand Up @@ -1687,7 +1688,7 @@ func (ds *DataSource) deriveCommonHandleTablePathStats(path *util.AccessPath, co
// If the `CountAfterAccess` is less than `stats.RowCount`, there must be some inconsistent stats info.
// We prefer the `stats.RowCount` because it could use more stats info to calculate the selectivity.
if path.CountAfterAccess < ds.StatsInfo().RowCount && !isIm {
path.CountAfterAccess = math.Min(ds.StatsInfo().RowCount/SelectionFactor, float64(ds.statisticTable.RealtimeCount))
path.CountAfterAccess = math.Min(ds.StatsInfo().RowCount/cost.SelectionFactor, float64(ds.statisticTable.RealtimeCount))
}
return nil
}
Expand Down Expand Up @@ -1773,7 +1774,7 @@ func (ds *DataSource) deriveTablePathStats(path *util.AccessPath, conds []expres
// If the `CountAfterAccess` is less than `stats.RowCount`, there must be some inconsistent stats info.
// We prefer the `stats.RowCount` because it could use more stats info to calculate the selectivity.
if path.CountAfterAccess < ds.StatsInfo().RowCount && !isIm {
path.CountAfterAccess = math.Min(ds.StatsInfo().RowCount/SelectionFactor, float64(ds.statisticTable.RealtimeCount))
path.CountAfterAccess = math.Min(ds.StatsInfo().RowCount/cost.SelectionFactor, float64(ds.statisticTable.RealtimeCount))
}
return err
}
Expand Down Expand Up @@ -1844,13 +1845,13 @@ func (ds *DataSource) deriveIndexPathStats(path *util.AccessPath, _ []expression
// If the `CountAfterAccess` is less than `stats.RowCount`, there must be some inconsistent stats info.
// We prefer the `stats.RowCount` because it could use more stats info to calculate the selectivity.
if path.CountAfterAccess < ds.StatsInfo().RowCount && !isIm {
path.CountAfterAccess = math.Min(ds.StatsInfo().RowCount/SelectionFactor, float64(ds.statisticTable.RealtimeCount))
path.CountAfterAccess = math.Min(ds.StatsInfo().RowCount/cost.SelectionFactor, float64(ds.statisticTable.RealtimeCount))
}
if path.IndexFilters != nil {
selectivity, _, err := cardinality.Selectivity(ds.SCtx(), ds.tableStats.HistColl, path.IndexFilters, nil)
if err != nil {
logutil.BgLogger().Debug("calculate selectivity failed, use selection factor", zap.Error(err))
selectivity = SelectionFactor
selectivity = cost.SelectionFactor
}
if isIm {
path.CountAfterIndex = path.CountAfterAccess * selectivity
Expand Down
7 changes: 4 additions & 3 deletions pkg/planner/core/physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/pingcap/tidb/pkg/parser/mysql"
"github.com/pingcap/tidb/pkg/planner/cardinality"
"github.com/pingcap/tidb/pkg/planner/core/base"
"github.com/pingcap/tidb/pkg/planner/core/cost"
"github.com/pingcap/tidb/pkg/planner/property"
"github.com/pingcap/tidb/pkg/planner/util"
"github.com/pingcap/tidb/pkg/planner/util/coreusage"
Expand Down Expand Up @@ -1915,10 +1916,10 @@ func (p *basePhysicalAgg) numDistinctFunc() (num int) {
func (p *basePhysicalAgg) getAggFuncCostFactor(isMPP bool) (factor float64) {
factor = 0.0
for _, agg := range p.AggFuncs {
if fac, ok := aggFuncFactor[agg.Name]; ok {
if fac, ok := cost.AggFuncFactor[agg.Name]; ok {
factor += fac
} else {
factor += aggFuncFactor["default"]
factor += cost.AggFuncFactor["default"]
}
}
if factor == 0 {
Expand All @@ -1927,7 +1928,7 @@ func (p *basePhysicalAgg) getAggFuncCostFactor(isMPP bool) (factor float64) {
// But in mpp cases, 2-phase is more usual. So we change this factor.
// TODO: This is still a little tricky and might cause regression. We should
// calibrate these factors and polish our cost model in the future.
factor = aggFuncFactor[ast.AggFuncFirstRow]
factor = cost.AggFuncFactor[ast.AggFuncFirstRow]
} else {
factor = 1.0
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/planner/core/plan_cost_detail.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

"github.com/pingcap/tidb/pkg/kv"
"github.com/pingcap/tidb/pkg/planner/core/base"
"github.com/pingcap/tidb/pkg/planner/core/cost"
"github.com/pingcap/tidb/pkg/planner/util/optimizetrace"
"github.com/pingcap/tidb/pkg/util/tracing"
)
Expand Down Expand Up @@ -195,7 +196,7 @@ func setPhysicalHashJoinCostDetail(p *PhysicalHashJoin, opt *optimizetrace.Physi
DiskFactor: diskFactor,
RowSize: rowSize,
ProbeDiskCost: &HashJoinProbeDiskCostDetail{
SelectionFactor: SelectionFactor,
SelectionFactor: cost.SelectionFactor,
NumPairs: numPairs,
HasConditions: len(p.LeftConditions)+len(p.RightConditions) > 0,
Cost: probeDiskCost,
Expand All @@ -217,7 +218,7 @@ func setPhysicalHashJoinCostDetail(p *PhysicalHashJoin, opt *optimizetrace.Physi
ProbeCost: &HashJoinProbeCostDetail{
NumPairs: numPairs,
HasConditions: len(p.LeftConditions)+len(p.RightConditions) > 0,
SelectionFactor: SelectionFactor,
SelectionFactor: cost.SelectionFactor,
ProbeRowCount: probeCnt,
Cost: probeCPUCost,
},
Expand Down
Loading

0 comments on commit f0a7447

Please sign in to comment.