diff --git a/parser/format/format.go b/parser/format/format.go index c963d5189538a..a4ac72532519d 100644 --- a/parser/format/format.go +++ b/parser/format/format.go @@ -349,16 +349,22 @@ func (rf RestoreFlags) HasRestoreForNonPrepPlanCache() bool { return rf.has(RestoreForNonPrepPlanCache) } +// RestoreWriter is the interface for `Restore` to write. +type RestoreWriter interface { + io.Writer + io.StringWriter +} + // RestoreCtx is `Restore` context to hold flags and writer. type RestoreCtx struct { Flags RestoreFlags - In io.Writer + In RestoreWriter DefaultDB string CTERestorer } // NewRestoreCtx returns a new `RestoreCtx`. -func NewRestoreCtx(flags RestoreFlags, in io.Writer) *RestoreCtx { +func NewRestoreCtx(flags RestoreFlags, in RestoreWriter) *RestoreCtx { return &RestoreCtx{Flags: flags, In: in, DefaultDB: ""} } @@ -427,12 +433,16 @@ func (ctx *RestoreCtx) WriteName(name string) { name = strings.Replace(name, "`", "``", -1) quotes = "`" } - fmt.Fprint(ctx.In, quotes, name, quotes) + + // use `WriteString` directly instead of `fmt.Fprint` to get a better performance. + ctx.In.WriteString(quotes) + ctx.In.WriteString(name) + ctx.In.WriteString(quotes) } // WritePlain writes the plain text into writer without any handling. func (ctx *RestoreCtx) WritePlain(plainText string) { - fmt.Fprint(ctx.In, plainText) + ctx.In.WriteString(plainText) } // WritePlainf write the plain text into writer without any handling. diff --git a/planner/core/plan_cache_param.go b/planner/core/plan_cache_param.go index 465bf677a65a4..1e2d808bcf231 100644 --- a/planner/core/plan_cache_param.go +++ b/planner/core/plan_cache_param.go @@ -15,9 +15,9 @@ package core import ( + "bytes" "context" "errors" - "strings" "sync" "github.com/pingcap/tidb/expression" @@ -41,8 +41,7 @@ var ( return pr }} paramCtxPool = sync.Pool{New: func() interface{} { - buf := new(strings.Builder) - buf.Reset() + buf := new(bytes.Buffer) restoreCtx := format.NewRestoreCtx(format.RestoreForNonPrepPlanCache|format.RestoreStringWithoutCharset|format.RestoreStringSingleQuotes|format.RestoreNameBackQuotes, buf) return restoreCtx }} @@ -106,14 +105,14 @@ func ParameterizeAST(ctx context.Context, sctx sessionctx.Context, stmt ast.Stmt defer func() { pr.Reset() paramReplacerPool.Put(pr) - pCtx.In.(*strings.Builder).Reset() + pCtx.In.(*bytes.Buffer).Reset() paramCtxPool.Put(pCtx) }() stmt.Accept(pr) if err := stmt.Restore(pCtx); err != nil { return "", nil, err } - paramSQL, params = pCtx.In.(*strings.Builder).String(), pr.params + paramSQL, params = pCtx.In.(*bytes.Buffer).String(), pr.params return }