Skip to content

Commit e491060

Browse files
authored
planner: don't recompute the hashcode when generated column substitution doesn't happen (#46450) (#46630)
close #42788
1 parent 38fb0eb commit e491060

File tree

4 files changed

+329
-12
lines changed

4 files changed

+329
-12
lines changed

planner/core/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ go_test(
212212
"point_get_plan_test.go",
213213
"prepare_test.go",
214214
"preprocess_test.go",
215+
"rule_generate_column_substitute_test.go",
215216
"rule_join_reorder_dp_test.go",
216217
"rule_join_reorder_test.go",
217218
"rule_result_reorder_test.go",

planner/core/logical_plans_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,26 @@ type plannerSuite struct {
4545
ctx sessionctx.Context
4646
}
4747

48+
func (p *plannerSuite) GetParser() *parser.Parser {
49+
return p.p
50+
}
51+
52+
func (p *plannerSuite) GetIS() infoschema.InfoSchema {
53+
return p.is
54+
}
55+
56+
func (p *plannerSuite) GetCtx() sessionctx.Context {
57+
return p.ctx
58+
}
59+
60+
func CreatePlannerSuite(sctx sessionctx.Context, is infoschema.InfoSchema) (s *plannerSuite) {
61+
s = new(plannerSuite)
62+
s.is = is
63+
s.p = parser.New()
64+
s.ctx = sctx
65+
return s
66+
}
67+
4868
func createPlannerSuite() (s *plannerSuite) {
4969
s = new(plannerSuite)
5070
tblInfos := []*model.TableInfo{

planner/core/rule_generate_column_substitute.go

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,15 @@ func collectGenerateColumn(lp LogicalPlan, exprToColumn ExprColumnMap) {
7373
}
7474
}
7575

76-
func tryToSubstituteExpr(expr *expression.Expression, lp LogicalPlan, candidateExpr expression.Expression, tp types.EvalType, schema *expression.Schema, col *expression.Column, opt *logicalOptimizeOp) {
76+
func tryToSubstituteExpr(expr *expression.Expression, lp LogicalPlan, candidateExpr expression.Expression, tp types.EvalType, schema *expression.Schema, col *expression.Column, opt *logicalOptimizeOp) bool {
77+
changed := false
7778
if (*expr).Equal(lp.SCtx(), candidateExpr) && candidateExpr.GetType().EvalType() == tp &&
7879
schema.ColumnIndex(col) != -1 {
7980
*expr = col
8081
appendSubstituteColumnStep(lp, candidateExpr, col, opt)
82+
changed = true
8183
}
84+
return changed
8285
}
8386

8487
func appendSubstituteColumnStep(lp LogicalPlan, candidateExpr expression.Expression, col *expression.Column, opt *logicalOptimizeOp) {
@@ -94,26 +97,38 @@ func appendSubstituteColumnStep(lp LogicalPlan, candidateExpr expression.Express
9497
opt.appendStepToCurrent(lp.ID(), lp.TP(), reason, action)
9598
}
9699

97-
func substituteExpression(cond expression.Expression, lp LogicalPlan, exprToColumn ExprColumnMap, schema *expression.Schema, opt *logicalOptimizeOp) {
100+
// SubstituteExpression is Exported for bench
101+
func SubstituteExpression(cond expression.Expression, lp LogicalPlan, exprToColumn ExprColumnMap, schema *expression.Schema, opt *logicalOptimizeOp) bool {
102+
return substituteExpression(cond, lp, exprToColumn, schema, opt)
103+
}
104+
105+
func substituteExpression(cond expression.Expression, lp LogicalPlan, exprToColumn ExprColumnMap, schema *expression.Schema, opt *logicalOptimizeOp) bool {
98106
sf, ok := cond.(*expression.ScalarFunction)
99107
if !ok {
100-
return
108+
return false
101109
}
102110
sctx := lp.SCtx().GetSessionVars().StmtCtx
111+
changed := false
112+
collectChanged := func(partial bool) {
113+
if partial && !changed {
114+
changed = true
115+
}
116+
}
103117
defer func() {
104118
// If the argument is not changed, hash code doesn't need to recount again.
105-
// But we always do it to keep the code simple and stupid.
106-
expression.ReHashCode(sf, sctx)
119+
if changed {
120+
expression.ReHashCode(sf, sctx)
121+
}
107122
}()
108123
var expr *expression.Expression
109124
var tp types.EvalType
110125
switch sf.FuncName.L {
111126
case ast.EQ, ast.LT, ast.LE, ast.GT, ast.GE:
112127
for candidateExpr, column := range exprToColumn {
113-
tryToSubstituteExpr(&sf.GetArgs()[1], lp, candidateExpr, sf.GetArgs()[0].GetType().EvalType(), schema, column, opt)
128+
collectChanged(tryToSubstituteExpr(&sf.GetArgs()[1], lp, candidateExpr, sf.GetArgs()[0].GetType().EvalType(), schema, column, opt))
114129
}
115130
for candidateExpr, column := range exprToColumn {
116-
tryToSubstituteExpr(&sf.GetArgs()[0], lp, candidateExpr, sf.GetArgs()[1].GetType().EvalType(), schema, column, opt)
131+
collectChanged(tryToSubstituteExpr(&sf.GetArgs()[0], lp, candidateExpr, sf.GetArgs()[1].GetType().EvalType(), schema, column, opt))
117132
}
118133
case ast.In:
119134
expr = &sf.GetArgs()[0]
@@ -129,21 +144,22 @@ func substituteExpression(cond expression.Expression, lp LogicalPlan, exprToColu
129144
}
130145
if canSubstitute {
131146
for candidateExpr, column := range exprToColumn {
132-
tryToSubstituteExpr(expr, lp, candidateExpr, tp, schema, column, opt)
147+
collectChanged(tryToSubstituteExpr(expr, lp, candidateExpr, tp, schema, column, opt))
133148
}
134149
}
135150
case ast.Like:
136151
expr = &sf.GetArgs()[0]
137152
tp = sf.GetArgs()[1].GetType().EvalType()
138153
for candidateExpr, column := range exprToColumn {
139-
tryToSubstituteExpr(expr, lp, candidateExpr, tp, schema, column, opt)
154+
collectChanged(tryToSubstituteExpr(expr, lp, candidateExpr, tp, schema, column, opt))
140155
}
141156
case ast.LogicOr, ast.LogicAnd:
142-
substituteExpression(sf.GetArgs()[0], lp, exprToColumn, schema, opt)
143-
substituteExpression(sf.GetArgs()[1], lp, exprToColumn, schema, opt)
157+
collectChanged(substituteExpression(sf.GetArgs()[0], lp, exprToColumn, schema, opt))
158+
collectChanged(substituteExpression(sf.GetArgs()[1], lp, exprToColumn, schema, opt))
144159
case ast.UnaryNot:
145-
substituteExpression(sf.GetArgs()[0], lp, exprToColumn, schema, opt)
160+
collectChanged(substituteExpression(sf.GetArgs()[0], lp, exprToColumn, schema, opt))
146161
}
162+
return changed
147163
}
148164

149165
func (gc *gcSubstituter) substitute(ctx context.Context, lp LogicalPlan, exprToColumn ExprColumnMap, opt *logicalOptimizeOp) LogicalPlan {

0 commit comments

Comments
 (0)