diff --git a/planner/core/plan_cache_param.go b/planner/core/plan_cache_param.go index abd8ce679f9c6..e71b2b0a5fb41 100644 --- a/planner/core/plan_cache_param.go +++ b/planner/core/plan_cache_param.go @@ -45,6 +45,9 @@ var ( restoreCtx := format.NewRestoreCtx(format.RestoreForNonPrepPlanCache|format.RestoreStringWithoutCharset|format.RestoreStringSingleQuotes|format.RestoreNameBackQuotes, buf) return restoreCtx }} + paramMakerPool = sync.Pool{New: func() interface{} { + return ast.NewParamMarkerExpr(0) + }} ) // paramReplacer is an ast.Visitor that replaces all values with `?` and collects them. @@ -72,8 +75,9 @@ func (pr *paramReplacer) Enter(in ast.Node) (out ast.Node, skipChildren bool) { } case *driver.ValueExpr: pr.params = append(pr.params, n) - param := ast.NewParamMarkerExpr(len(pr.params) - 1) // offset is used as order in non-prepared plan cache. - n.Datum.Copy(¶m.(*driver.ParamMarkerExpr).Datum) // init the ParamMakerExpr's Datum + param := paramMakerPool.Get().(*driver.ParamMarkerExpr) + param.Offset = len(pr.params) - 1 // offset is used as order in non-prepared plan cache. + n.Datum.Copy(¶m.Datum) // init the ParamMakerExpr's Datum return param, true } return in, false @@ -129,7 +133,9 @@ func (pr *paramRestorer) Enter(in ast.Node) (out ast.Node, skipChildren bool) { return nil, true } // offset is used as order in non-prepared plan cache. - return pr.params[n.Offset], true + offset := n.Offset + paramMakerPool.Put(n) + return pr.params[offset], true } if pr.err != nil { return nil, true @@ -162,6 +168,7 @@ func RestoreASTWithParams(ctx context.Context, _ sessionctx.Context, stmt ast.St func Params2Expressions(params []*driver.ValueExpr) []expression.Expression { exprs := make([]expression.Expression, 0, len(params)) for _, p := range params { + // TODO: add a sync.Pool for type.FieldType and expression.Constant here. tp := new(types.FieldType) types.InferParamTypeFromDatum(&p.Datum, tp) exprs = append(exprs, &expression.Constant{ diff --git a/planner/core/plan_cache_param_test.go b/planner/core/plan_cache_param_test.go index 9d1da6019826b..b051b61a44d30 100644 --- a/planner/core/plan_cache_param_test.go +++ b/planner/core/plan_cache_param_test.go @@ -145,3 +145,15 @@ func BenchmarkParameterizeInsert(b *testing.B) { ParameterizeAST(context.Background(), sctx, stmt) } } + +func BenchmarkGetParamSQL(b *testing.B) { + paymentInsertHistory := `INSERT INTO history (h_c_d_id, h_c_w_id, h_c_id, h_d_id, h_w_id, h_date, h_amount, h_data) VALUES (1, 2, 3, 4, 5, 6, 7, 8)` + stmt, err := parser.New().ParseOneStmt(paymentInsertHistory, "", "") + require.Nil(b, err) + sctx := MockContext() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + GetParamSQLFromAST(context.Background(), sctx, stmt) + } +}