From 2479f5226734f16d4d1e04b0e0443f57eb9b37f1 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 14:49:45 +0800 Subject: [PATCH 01/11] fixup --- planner/core/plan_cache.go | 40 ++++++++++++++++++++++++++++++++++++++ session/session.go | 19 ++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/planner/core/plan_cache.go b/planner/core/plan_cache.go index cf087d9af43cf..e05700d124379 100644 --- a/planner/core/plan_cache.go +++ b/planner/core/plan_cache.go @@ -16,6 +16,7 @@ package core import ( "context" + "github.com/pingcap/tidb/sessiontxn/staleread" "github.com/pingcap/errors" "github.com/pingcap/tidb/bindinfo" @@ -631,3 +632,42 @@ func GetBindSQL4PlanCache(sctx sessionctx.Context, preparedStmt *CachedPrepareSt } return "", ignore } + +// IsPointPlanShortPathOK check if we can execute using plan cached in prepared structure +// Be careful with the short path, current precondition is ths cached plan satisfying +// IsPointGetWithPKOrUniqueKeyByAutoCommit +func IsPointPlanShortPathOK(sctx sessionctx.Context, preparedStmt *CachedPrepareStmt) (bool, error) { + prepared := preparedStmt.PreparedAst + if prepared.CachedPlan == nil || staleread.IsStmtStaleness(sctx) { + return false, nil + } + // check auto commit + if !IsAutoCommitTxn(sctx) { + return false, nil + } + is := sctx.GetInfoSchema().(infoschema.InfoSchema) + if prepared.SchemaVersion != is.SchemaMetaVersion() { + prepared.CachedPlan = nil + preparedStmt.ColumnInfos = nil + return false, nil + } + // maybe we'd better check cached plan type here, current + // only point select/update will be cached, see "getPhysicalPlan" func + var ok bool + var err error + switch prepared.CachedPlan.(type) { + case *PointGetPlan: + ok = true + case *Update: + pointUpdate := prepared.CachedPlan.(*Update) + _, ok = pointUpdate.SelectPlan.(*PointGetPlan) + if !ok { + err = errors.Errorf("cached update plan not point update") + prepared.CachedPlan = nil + return false, err + } + default: + ok = false + } + return ok, err +} diff --git a/session/session.go b/session/session.go index 5ea8f461f70fa..4da540fdba39b 100644 --- a/session/session.go +++ b/session/session.go @@ -2302,6 +2302,25 @@ func (s *session) preparedStmtExec(ctx context.Context, execStmt *ast.ExecuteStm } sessionExecuteCompileDurationGeneral.Observe(time.Since(s.sessionVars.StartTime).Seconds()) logGeneralQuery(st, s, true) + + pointShortPathOK, err := plannercore.IsPointPlanShortPathOK(s, prepareStmt) + if err != nil { + return nil, err + } + if pointShortPathOK { + stmtCtx := s.GetSessionVars().StmtCtx + switch st.Plan.(type) { + case *plannercore.PointGetPlan: + resultSet, err := st.PointGet(ctx) + s.txn.changeToInvalid() + return resultSet, err + case *plannercore.Update: + stmtCtx.Priority = kv.PriorityHigh + resultSet, err := runStmt(ctx, s, st) + return resultSet, err + } + } + return runStmt(ctx, s, st) } From 273e0660d16bf2300697efba9225bf178791d555 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 15:06:27 +0800 Subject: [PATCH 02/11] fixup --- planner/core/plan_cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/plan_cache.go b/planner/core/plan_cache.go index e05700d124379..053738b215246 100644 --- a/planner/core/plan_cache.go +++ b/planner/core/plan_cache.go @@ -16,7 +16,6 @@ package core import ( "context" - "github.com/pingcap/tidb/sessiontxn/staleread" "github.com/pingcap/errors" "github.com/pingcap/tidb/bindinfo" @@ -31,6 +30,7 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/sessiontxn/staleread" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" From b59dcf86ff0cfaa1a7d569927719b31177036b2f Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 16:40:37 +0800 Subject: [PATCH 03/11] fixup --- session/bench_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/session/bench_test.go b/session/bench_test.go index 0550446a3d1fb..dba8b622752db 100644 --- a/session/bench_test.go +++ b/session/bench_test.go @@ -324,10 +324,11 @@ func BenchmarkPreparedPointGet(b *testing.B) { b.Fatal(err) } + params := expression.Args2Expressions4Test(64) alloc := chunk.NewAllocator() b.ResetTimer() for i := 0; i < b.N; i++ { - rs, err := se.ExecutePreparedStmt(ctx, stmtID, expression.Args2Expressions4Test(64)) + rs, err := se.ExecutePreparedStmt(ctx, stmtID, params) if err != nil { b.Fatal(err) } From 7c799ce0c2cf3d54994b6f31c8806845e01bb9be Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 16:59:37 +0800 Subject: [PATCH 04/11] fixup fixup fixup fixup --- executor/prepared.go | 17 +++++++++++++++++ session/session.go | 20 ++++---------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/executor/prepared.go b/executor/prepared.go index 4329165915f39..fab957188851e 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -346,6 +346,23 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, if err != nil { return nil, err } + pointPlanShortPathOK, err := plannercore.IsPointPlanShortPathOK(sctx, preparedObj) + if pointPlanShortPathOK && err == nil { + if ep, ok := execPlan.(*plannercore.Execute); ok { + if pointPlan, ok := ep.Plan.(*plannercore.PointGetPlan); ok { + // set for point plan short path + stmtCtx := sctx.GetSessionVars().StmtCtx + stmt.Text = preparedObj.PreparedAst.Stmt.Text() + stmtCtx.OriginalSQL = stmt.Text + stmtCtx.SetPlan(execPlan) + stmtCtx.InitSQLDigest(preparedObj.NormalizedSQL, preparedObj.SQLDigest) + stmtCtx.SetPlanDigest(preparedObj.NormalizedPlan, preparedObj.PlanDigest) + stmt.Plan = pointPlan + stmt.PsStmt = preparedObj + } + } + } + stmtCtx := sctx.GetSessionVars().StmtCtx stmt.Text = preparedObj.PreparedAst.Stmt.Text() stmtCtx.OriginalSQL = stmt.Text diff --git a/session/session.go b/session/session.go index 4da540fdba39b..c20b5afe8ec3d 100644 --- a/session/session.go +++ b/session/session.go @@ -2303,22 +2303,10 @@ func (s *session) preparedStmtExec(ctx context.Context, execStmt *ast.ExecuteStm sessionExecuteCompileDurationGeneral.Observe(time.Since(s.sessionVars.StartTime).Seconds()) logGeneralQuery(st, s, true) - pointShortPathOK, err := plannercore.IsPointPlanShortPathOK(s, prepareStmt) - if err != nil { - return nil, err - } - if pointShortPathOK { - stmtCtx := s.GetSessionVars().StmtCtx - switch st.Plan.(type) { - case *plannercore.PointGetPlan: - resultSet, err := st.PointGet(ctx) - s.txn.changeToInvalid() - return resultSet, err - case *plannercore.Update: - stmtCtx.Priority = kv.PriorityHigh - resultSet, err := runStmt(ctx, s, st) - return resultSet, err - } + if st.PsStmt != nil { // point plan short path + resultSet, err := st.PointGet(ctx) + s.txn.changeToInvalid() + return resultSet, err } return runStmt(ctx, s, st) From d5da26328714c6c40541d98c46b74ec1efb593bf Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 17:40:56 +0800 Subject: [PATCH 05/11] fixup --- executor/prepared.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/executor/prepared.go b/executor/prepared.go index fab957188851e..775fd52cbb250 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -346,26 +346,22 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, if err != nil { return nil, err } + stmtCtx := sctx.GetSessionVars().StmtCtx + stmt.Text = preparedObj.PreparedAst.Stmt.Text() + stmtCtx.OriginalSQL = stmt.Text + stmtCtx.InitSQLDigest(preparedObj.NormalizedSQL, preparedObj.SQLDigest) + + // handle point plan short path specially pointPlanShortPathOK, err := plannercore.IsPointPlanShortPathOK(sctx, preparedObj) if pointPlanShortPathOK && err == nil { if ep, ok := execPlan.(*plannercore.Execute); ok { if pointPlan, ok := ep.Plan.(*plannercore.PointGetPlan); ok { - // set for point plan short path - stmtCtx := sctx.GetSessionVars().StmtCtx - stmt.Text = preparedObj.PreparedAst.Stmt.Text() - stmtCtx.OriginalSQL = stmt.Text stmtCtx.SetPlan(execPlan) - stmtCtx.InitSQLDigest(preparedObj.NormalizedSQL, preparedObj.SQLDigest) stmtCtx.SetPlanDigest(preparedObj.NormalizedPlan, preparedObj.PlanDigest) stmt.Plan = pointPlan stmt.PsStmt = preparedObj } } } - - stmtCtx := sctx.GetSessionVars().StmtCtx - stmt.Text = preparedObj.PreparedAst.Stmt.Text() - stmtCtx.OriginalSQL = stmt.Text - stmtCtx.InitSQLDigest(preparedObj.NormalizedSQL, preparedObj.SQLDigest) return stmt, nil } From dca80080317015f59252a27181923f1e05a26290 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 18:05:35 +0800 Subject: [PATCH 06/11] fixup --- executor/prepared.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/executor/prepared.go b/executor/prepared.go index 775fd52cbb250..6d7628cde11d3 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -16,6 +16,7 @@ package executor import ( "context" + "github.com/pingcap/tidb/sessiontxn/staleread" "math" "time" @@ -354,6 +355,12 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, // handle point plan short path specially pointPlanShortPathOK, err := plannercore.IsPointPlanShortPathOK(sctx, preparedObj) if pointPlanShortPathOK && err == nil { + failpoint.Inject("assertTxnManagerInCachedPlanExec", func() { + sessiontxn.RecordAssert(sctx, "assertTxnManagerInCachedPlanExec", true) + // stale read should not reach here + staleread.AssertStmtStaleness(sctx, false) + }) + if ep, ok := execPlan.(*plannercore.Execute); ok { if pointPlan, ok := ep.Plan.(*plannercore.PointGetPlan); ok { stmtCtx.SetPlan(execPlan) From 0bdd253b6983c32b4dd0eb5ef116918de8a04c4a Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 18:09:15 +0800 Subject: [PATCH 07/11] fixup --- executor/prepared.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/executor/prepared.go b/executor/prepared.go index 6d7628cde11d3..775fd52cbb250 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -16,7 +16,6 @@ package executor import ( "context" - "github.com/pingcap/tidb/sessiontxn/staleread" "math" "time" @@ -355,12 +354,6 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, // handle point plan short path specially pointPlanShortPathOK, err := plannercore.IsPointPlanShortPathOK(sctx, preparedObj) if pointPlanShortPathOK && err == nil { - failpoint.Inject("assertTxnManagerInCachedPlanExec", func() { - sessiontxn.RecordAssert(sctx, "assertTxnManagerInCachedPlanExec", true) - // stale read should not reach here - staleread.AssertStmtStaleness(sctx, false) - }) - if ep, ok := execPlan.(*plannercore.Execute); ok { if pointPlan, ok := ep.Plan.(*plannercore.PointGetPlan); ok { stmtCtx.SetPlan(execPlan) From b9308fe2476af52c508fc1e807e321b9dce4113e Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 18:27:04 +0800 Subject: [PATCH 08/11] fixup --- executor/prepared.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/executor/prepared.go b/executor/prepared.go index 775fd52cbb250..8b13f6d1e6022 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -360,6 +360,9 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, stmtCtx.SetPlanDigest(preparedObj.NormalizedPlan, preparedObj.PlanDigest) stmt.Plan = pointPlan stmt.PsStmt = preparedObj + } else { + // invalid the previous cached point plan + preparedObj.PreparedAst.CachedPlan = nil } } } From 5af9f79995f2b14f847c1d82655285f9521518bb Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 18:46:44 +0800 Subject: [PATCH 09/11] fixup --- planner/core/plan_cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/plan_cache.go b/planner/core/plan_cache.go index 053738b215246..2960cda67527f 100644 --- a/planner/core/plan_cache.go +++ b/planner/core/plan_cache.go @@ -645,7 +645,7 @@ func IsPointPlanShortPathOK(sctx sessionctx.Context, preparedStmt *CachedPrepare if !IsAutoCommitTxn(sctx) { return false, nil } - is := sctx.GetInfoSchema().(infoschema.InfoSchema) + is := sctx.GetDomainInfoSchema().(infoschema.InfoSchema) if prepared.SchemaVersion != is.SchemaMetaVersion() { prepared.CachedPlan = nil preparedStmt.ColumnInfos = nil From 3bc8a40cc43a0202ebd8dcbe89f53687bb567dae Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 19:10:08 +0800 Subject: [PATCH 10/11] fixup --- executor/prepared.go | 2 +- planner/core/plan_cache.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/executor/prepared.go b/executor/prepared.go index 8b13f6d1e6022..3a15c4d0f6708 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -352,7 +352,7 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, stmtCtx.InitSQLDigest(preparedObj.NormalizedSQL, preparedObj.SQLDigest) // handle point plan short path specially - pointPlanShortPathOK, err := plannercore.IsPointPlanShortPathOK(sctx, preparedObj) + pointPlanShortPathOK, err := plannercore.IsPointPlanShortPathOK(sctx, is, preparedObj) if pointPlanShortPathOK && err == nil { if ep, ok := execPlan.(*plannercore.Execute); ok { if pointPlan, ok := ep.Plan.(*plannercore.PointGetPlan); ok { diff --git a/planner/core/plan_cache.go b/planner/core/plan_cache.go index 2960cda67527f..ca1d6014c3c23 100644 --- a/planner/core/plan_cache.go +++ b/planner/core/plan_cache.go @@ -636,7 +636,7 @@ func GetBindSQL4PlanCache(sctx sessionctx.Context, preparedStmt *CachedPrepareSt // IsPointPlanShortPathOK check if we can execute using plan cached in prepared structure // Be careful with the short path, current precondition is ths cached plan satisfying // IsPointGetWithPKOrUniqueKeyByAutoCommit -func IsPointPlanShortPathOK(sctx sessionctx.Context, preparedStmt *CachedPrepareStmt) (bool, error) { +func IsPointPlanShortPathOK(sctx sessionctx.Context, is infoschema.InfoSchema, preparedStmt *CachedPrepareStmt) (bool, error) { prepared := preparedStmt.PreparedAst if prepared.CachedPlan == nil || staleread.IsStmtStaleness(sctx) { return false, nil @@ -645,7 +645,6 @@ func IsPointPlanShortPathOK(sctx sessionctx.Context, preparedStmt *CachedPrepare if !IsAutoCommitTxn(sctx) { return false, nil } - is := sctx.GetDomainInfoSchema().(infoschema.InfoSchema) if prepared.SchemaVersion != is.SchemaMetaVersion() { prepared.CachedPlan = nil preparedStmt.ColumnInfos = nil From 367ff95f7464b0f09205162e9454a34c69956498 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 9 Aug 2022 19:11:55 +0800 Subject: [PATCH 11/11] fixup --- executor/prepared.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/executor/prepared.go b/executor/prepared.go index 3a15c4d0f6708..715d438c90943 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -323,6 +323,16 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, defer func() { sctx.GetSessionVars().DurationCompile = time.Since(startTime) }() + + preparedObj, err := plannercore.GetPreparedStmt(execStmt, sctx.GetSessionVars()) + if err != nil { + return nil, err + } + pointPlanShortPathOK, err := plannercore.IsPointPlanShortPathOK(sctx, is, preparedObj) + if err != nil { + return nil, err + } + execPlan, names, err := planner.Optimize(ctx, sctx, execStmt, is) if err != nil { return nil, err @@ -342,18 +352,13 @@ func CompileExecutePreparedStmt(ctx context.Context, sctx sessionctx.Context, OutputNames: names, Ti: &TelemetryInfo{}, } - preparedObj, err := plannercore.GetPreparedStmt(execStmt, sctx.GetSessionVars()) - if err != nil { - return nil, err - } stmtCtx := sctx.GetSessionVars().StmtCtx stmt.Text = preparedObj.PreparedAst.Stmt.Text() stmtCtx.OriginalSQL = stmt.Text stmtCtx.InitSQLDigest(preparedObj.NormalizedSQL, preparedObj.SQLDigest) // handle point plan short path specially - pointPlanShortPathOK, err := plannercore.IsPointPlanShortPathOK(sctx, is, preparedObj) - if pointPlanShortPathOK && err == nil { + if pointPlanShortPathOK { if ep, ok := execPlan.(*plannercore.Execute); ok { if pointPlan, ok := ep.Plan.(*plannercore.PointGetPlan); ok { stmtCtx.SetPlan(execPlan)