Skip to content

Commit f2faaa4

Browse files
authored
planner: don't recompute the hashcode when generated column substitution doesn't happen (#46450) (#46628)
close #42788
1 parent d4cafec commit f2faaa4

File tree

3 files changed

+331
-13
lines changed

3 files changed

+331
-13
lines changed

planner/core/logical_plan_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: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,32 +74,47 @@ func collectGenerateColumn(lp LogicalPlan, exprToColumn ExprColumnMap) {
7474
}
7575
}
7676

77-
func tryToSubstituteExpr(expr *expression.Expression, sctx sessionctx.Context, candidateExpr expression.Expression, tp types.EvalType, schema *expression.Schema, col *expression.Column) {
78-
if (*expr).Equal(sctx, candidateExpr) && candidateExpr.GetType().EvalType() == tp &&
77+
func tryToSubstituteExpr(expr *expression.Expression, sessionCtx sessionctx.Context, candidateExpr expression.Expression, tp types.EvalType, schema *expression.Schema, col *expression.Column) bool {
78+
changed := false
79+
if (*expr).Equal(sessionCtx, candidateExpr) && candidateExpr.GetType().EvalType() == tp &&
7980
schema.ColumnIndex(col) != -1 {
8081
*expr = col
82+
changed = true
8183
}
84+
return changed
8285
}
8386

84-
func substituteExpression(cond expression.Expression, sctx *stmtctx.StatementContext, sessionCtx sessionctx.Context, exprToColumn ExprColumnMap, schema *expression.Schema) {
87+
// SubstituteExpression is Exported for bench
88+
func SubstituteExpression(cond expression.Expression, sctx *stmtctx.StatementContext, sessionCtx sessionctx.Context, exprToColumn ExprColumnMap, schema *expression.Schema) bool {
89+
return substituteExpression(cond, sctx, sessionCtx, exprToColumn, schema)
90+
}
91+
92+
func substituteExpression(cond expression.Expression, sctx *stmtctx.StatementContext, sessionCtx sessionctx.Context, exprToColumn ExprColumnMap, schema *expression.Schema) bool {
8593
sf, ok := cond.(*expression.ScalarFunction)
8694
if !ok {
87-
return
95+
return false
96+
}
97+
changed := false
98+
collectChanged := func(partial bool) {
99+
if partial && !changed {
100+
changed = true
101+
}
88102
}
89103
defer func() {
90104
// If the argument is not changed, hash code doesn't need to recount again.
91-
// But we always do it to keep the code simple and stupid.
92-
expression.ReHashCode(sf, sctx)
105+
if changed {
106+
expression.ReHashCode(sf, sctx)
107+
}
93108
}()
94109
var expr *expression.Expression
95110
var tp types.EvalType
96111
switch sf.FuncName.L {
97112
case ast.EQ, ast.LT, ast.LE, ast.GT, ast.GE:
98113
for candidateExpr, column := range exprToColumn {
99-
tryToSubstituteExpr(&sf.GetArgs()[1], sessionCtx, candidateExpr, sf.GetArgs()[0].GetType().EvalType(), schema, column)
114+
collectChanged(tryToSubstituteExpr(&sf.GetArgs()[1], sessionCtx, candidateExpr, sf.GetArgs()[0].GetType().EvalType(), schema, column))
100115
}
101116
for candidateExpr, column := range exprToColumn {
102-
tryToSubstituteExpr(&sf.GetArgs()[0], sessionCtx, candidateExpr, sf.GetArgs()[1].GetType().EvalType(), schema, column)
117+
collectChanged(tryToSubstituteExpr(&sf.GetArgs()[0], sessionCtx, candidateExpr, sf.GetArgs()[1].GetType().EvalType(), schema, column))
103118
}
104119
case ast.In:
105120
expr = &sf.GetArgs()[0]
@@ -115,21 +130,22 @@ func substituteExpression(cond expression.Expression, sctx *stmtctx.StatementCon
115130
}
116131
if canSubstitute {
117132
for candidateExpr, column := range exprToColumn {
118-
tryToSubstituteExpr(expr, sessionCtx, candidateExpr, tp, schema, column)
133+
collectChanged(tryToSubstituteExpr(expr, sessionCtx, candidateExpr, tp, schema, column))
119134
}
120135
}
121136
case ast.Like:
122137
expr = &sf.GetArgs()[0]
123138
tp = sf.GetArgs()[1].GetType().EvalType()
124139
for candidateExpr, column := range exprToColumn {
125-
tryToSubstituteExpr(expr, sessionCtx, candidateExpr, tp, schema, column)
140+
collectChanged(tryToSubstituteExpr(expr, sessionCtx, candidateExpr, tp, schema, column))
126141
}
127142
case ast.LogicOr, ast.LogicAnd:
128-
substituteExpression(sf.GetArgs()[0], sctx, sessionCtx, exprToColumn, schema)
129-
substituteExpression(sf.GetArgs()[1], sctx, sessionCtx, exprToColumn, schema)
143+
collectChanged(substituteExpression(sf.GetArgs()[0], sctx, sessionCtx, exprToColumn, schema))
144+
collectChanged(substituteExpression(sf.GetArgs()[1], sctx, sessionCtx, exprToColumn, schema))
130145
case ast.UnaryNot:
131-
substituteExpression(sf.GetArgs()[0], sctx, sessionCtx, exprToColumn, schema)
146+
collectChanged(substituteExpression(sf.GetArgs()[0], sctx, sessionCtx, exprToColumn, schema))
132147
}
148+
return changed
133149
}
134150

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

0 commit comments

Comments
 (0)