Skip to content

Commit 41c1642

Browse files
authored
planner: don't recompute the hashcode when generated column substitution doesn't happen (#46450)
1 parent 1901239 commit 41c1642

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
@@ -221,6 +221,7 @@ go_test(
221221
"planbuilder_test.go",
222222
"point_get_plan_test.go",
223223
"preprocess_test.go",
224+
"rule_generate_column_substitute_test.go",
224225
"rule_join_reorder_dp_test.go",
225226
"rule_join_reorder_test.go",
226227
"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
@@ -47,6 +47,26 @@ type plannerSuite struct {
4747
ctx sessionctx.Context
4848
}
4949

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

planner/core/rule_generate_column_substitute.go

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,15 @@ func collectGenerateColumn(lp LogicalPlan, exprToColumn ExprColumnMap) {
7676
}
7777
}
7878

79-
func tryToSubstituteExpr(expr *expression.Expression, lp LogicalPlan, candidateExpr expression.Expression, tp types.EvalType, schema *expression.Schema, col *expression.Column, opt *logicalOptimizeOp) {
79+
func tryToSubstituteExpr(expr *expression.Expression, lp LogicalPlan, candidateExpr expression.Expression, tp types.EvalType, schema *expression.Schema, col *expression.Column, opt *logicalOptimizeOp) bool {
80+
changed := false
8081
if (*expr).Equal(lp.SCtx(), candidateExpr) && candidateExpr.GetType().EvalType() == tp &&
8182
schema.ColumnIndex(col) != -1 {
8283
*expr = col
8384
appendSubstituteColumnStep(lp, candidateExpr, col, opt)
85+
changed = true
8486
}
87+
return changed
8588
}
8689

8790
func appendSubstituteColumnStep(lp LogicalPlan, candidateExpr expression.Expression, col *expression.Column, opt *logicalOptimizeOp) {
@@ -97,26 +100,38 @@ func appendSubstituteColumnStep(lp LogicalPlan, candidateExpr expression.Express
97100
opt.appendStepToCurrent(lp.ID(), lp.TP(), reason, action)
98101
}
99102

100-
func substituteExpression(cond expression.Expression, lp LogicalPlan, exprToColumn ExprColumnMap, schema *expression.Schema, opt *logicalOptimizeOp) {
103+
// SubstituteExpression is Exported for bench
104+
func SubstituteExpression(cond expression.Expression, lp LogicalPlan, exprToColumn ExprColumnMap, schema *expression.Schema, opt *logicalOptimizeOp) bool {
105+
return substituteExpression(cond, lp, exprToColumn, schema, opt)
106+
}
107+
108+
func substituteExpression(cond expression.Expression, lp LogicalPlan, exprToColumn ExprColumnMap, schema *expression.Schema, opt *logicalOptimizeOp) bool {
101109
sf, ok := cond.(*expression.ScalarFunction)
102110
if !ok {
103-
return
111+
return false
104112
}
105113
sctx := lp.SCtx().GetSessionVars().StmtCtx
114+
changed := false
115+
collectChanged := func(partial bool) {
116+
if partial && !changed {
117+
changed = true
118+
}
119+
}
106120
defer func() {
107121
// If the argument is not changed, hash code doesn't need to recount again.
108-
// But we always do it to keep the code simple and stupid.
109-
expression.ReHashCode(sf, sctx)
122+
if changed {
123+
expression.ReHashCode(sf, sctx)
124+
}
110125
}()
111126
var expr *expression.Expression
112127
var tp types.EvalType
113128
switch sf.FuncName.L {
114129
case ast.EQ, ast.LT, ast.LE, ast.GT, ast.GE:
115130
for candidateExpr, column := range exprToColumn {
116-
tryToSubstituteExpr(&sf.GetArgs()[1], lp, candidateExpr, sf.GetArgs()[0].GetType().EvalType(), schema, column, opt)
131+
collectChanged(tryToSubstituteExpr(&sf.GetArgs()[1], lp, candidateExpr, sf.GetArgs()[0].GetType().EvalType(), schema, column, opt))
117132
}
118133
for candidateExpr, column := range exprToColumn {
119-
tryToSubstituteExpr(&sf.GetArgs()[0], lp, candidateExpr, sf.GetArgs()[1].GetType().EvalType(), schema, column, opt)
134+
collectChanged(tryToSubstituteExpr(&sf.GetArgs()[0], lp, candidateExpr, sf.GetArgs()[1].GetType().EvalType(), schema, column, opt))
120135
}
121136
case ast.In:
122137
expr = &sf.GetArgs()[0]
@@ -132,21 +147,22 @@ func substituteExpression(cond expression.Expression, lp LogicalPlan, exprToColu
132147
}
133148
if canSubstitute {
134149
for candidateExpr, column := range exprToColumn {
135-
tryToSubstituteExpr(expr, lp, candidateExpr, tp, schema, column, opt)
150+
collectChanged(tryToSubstituteExpr(expr, lp, candidateExpr, tp, schema, column, opt))
136151
}
137152
}
138153
case ast.Like:
139154
expr = &sf.GetArgs()[0]
140155
tp = sf.GetArgs()[1].GetType().EvalType()
141156
for candidateExpr, column := range exprToColumn {
142-
tryToSubstituteExpr(expr, lp, candidateExpr, tp, schema, column, opt)
157+
collectChanged(tryToSubstituteExpr(expr, lp, candidateExpr, tp, schema, column, opt))
143158
}
144159
case ast.LogicOr, ast.LogicAnd:
145-
substituteExpression(sf.GetArgs()[0], lp, exprToColumn, schema, opt)
146-
substituteExpression(sf.GetArgs()[1], lp, exprToColumn, schema, opt)
160+
collectChanged(substituteExpression(sf.GetArgs()[0], lp, exprToColumn, schema, opt))
161+
collectChanged(substituteExpression(sf.GetArgs()[1], lp, exprToColumn, schema, opt))
147162
case ast.UnaryNot:
148-
substituteExpression(sf.GetArgs()[0], lp, exprToColumn, schema, opt)
163+
collectChanged(substituteExpression(sf.GetArgs()[0], lp, exprToColumn, schema, opt))
149164
}
165+
return changed
150166
}
151167

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

0 commit comments

Comments
 (0)