From e7db5338101b44ba589fcd264c5247d40ca13882 Mon Sep 17 00:00:00 2001 From: mmyj Date: Wed, 12 May 2021 19:49:40 +0800 Subject: [PATCH] planner: ignore lock for temporary table of PointGet and BatchPointGet (#24540) --- planner/core/integration_test.go | 26 +++++++++++++++ planner/core/optimizer.go | 25 ++++++++++++++ planner/core/point_get_plan.go | 10 ++++-- .../core/testdata/integration_suite_in.json | 9 +++++ .../core/testdata/integration_suite_out.json | 33 +++++++++++++++++++ 5 files changed, 101 insertions(+), 2 deletions(-) diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 98ab7b7898370..9e8eaa9204af9 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -3832,3 +3832,29 @@ func (s *testIntegrationSerialSuite) TestEnforceMPP(c *C) { " └─Selection_20 10.00 285020.00 batchCop[tiflash] eq(test.t.a, 1)", " └─TableFullScan_19 10000.00 255020.00 batchCop[tiflash] table:t keep order:false, stats:pseudo")) } + +func (s *testIntegrationSuite) TestEliminateLockForTemporaryTable(c *C) { + tk := testkit.NewTestKit(c, s.store) + + tk.MustExec("use test;") + tk.MustExec("create global temporary table t1 (a int primary key, b int, c int, index i_b(b)) on commit delete rows;") + defer func() { + tk.MustExec("drop global temporary table if exists t1;") + }() + tk.MustExec("begin;") + tk.MustExec("insert t1 values (8,8,9);") + + var input []string + var output []struct { + SQL string + Plan []string + } + s.testData.GetTestCases(c, &input, &output) + for i, tt := range input { + s.testData.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) + }) + tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...)) + } +} diff --git a/planner/core/optimizer.go b/planner/core/optimizer.go index 59c228767171a..0c1c4a668d3c8 100644 --- a/planner/core/optimizer.go +++ b/planner/core/optimizer.go @@ -20,6 +20,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/parser/ast" "github.com/pingcap/parser/auth" + "github.com/pingcap/parser/model" "github.com/pingcap/parser/mysql" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/expression" @@ -186,6 +187,7 @@ func postOptimize(sctx sessionctx.Context, plan PhysicalPlan) PhysicalPlan { plan = InjectExtraProjection(plan) mergeContinuousSelections(plan) plan = eliminateUnionScanAndLock(sctx, plan) + plan = eliminateLockForTemporaryTable(plan) plan = enableParallelApply(sctx, plan) return plan } @@ -322,6 +324,29 @@ func eliminateUnionScanAndLock(sctx sessionctx.Context, p PhysicalPlan) Physical }) } +// eliminateLockForTemporaryTable eliminates lock for the temporary table. +func eliminateLockForTemporaryTable(p PhysicalPlan) PhysicalPlan { + iteratePhysicalPlan(p, func(p PhysicalPlan) bool { + if len(p.Children()) > 1 { + return false + } + switch x := p.(type) { + case *PointGetPlan: + if x.TblInfo.TempTableType != model.TempTableNone { + x.Lock = false + x.LockWaitTime = 0 + } + case *BatchPointGetPlan: + if x.TblInfo.TempTableType != model.TempTableNone { + x.Lock = false + x.LockWaitTime = 0 + } + } + return true + }) + return p +} + func iteratePhysicalPlan(p PhysicalPlan, f func(p PhysicalPlan) bool) { if !f(p) { return diff --git a/planner/core/point_get_plan.go b/planner/core/point_get_plan.go index f7edbc1648819..fbc0bf9333a29 100644 --- a/planner/core/point_get_plan.go +++ b/planner/core/point_get_plan.go @@ -462,7 +462,10 @@ func TryFastPlan(ctx sessionctx.Context, node ast.Node) (p Plan) { if tidbutil.IsMemDB(fp.dbName) { return nil } - fp.Lock, fp.LockWaitTime = getLockWaitTime(ctx, x.LockInfo) + // ignore lock for temporary table. + if fp.TblInfo.TempTableType == model.TempTableNone { + fp.Lock, fp.LockWaitTime = getLockWaitTime(ctx, x.LockInfo) + } p = fp return } @@ -480,7 +483,10 @@ func TryFastPlan(ctx sessionctx.Context, node ast.Node) (p Plan) { p = tableDual.Init(ctx, &property.StatsInfo{}, 0) return } - fp.Lock, fp.LockWaitTime = getLockWaitTime(ctx, x.LockInfo) + // ignore lock for temporary table. + if fp.TblInfo.TempTableType == model.TempTableNone { + fp.Lock, fp.LockWaitTime = getLockWaitTime(ctx, x.LockInfo) + } p = fp return } diff --git a/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index 087b32110e18f..f386f8d7f24e8 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -294,5 +294,14 @@ "select sum(1) from s1", "select count(1) as cnt from s1 union select count(1) as cnt from s2" ] + }, + { + "name": "TestEliminateLockForTemporaryTable", + "cases": [ + "select * from t1 where a = 2 for update", + "select * from t1 where a in (1,2) for update", + "select c + 1 from t1 where a = 2 and c = 2 for update", + "select c + 1 from t1 where a in (1,2) and c = 2 for update" + ] } ] diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index 7c735fcb5657c..902ff19276cc0 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -1564,5 +1564,38 @@ ] } ] + }, + { + "Name": "TestEliminateLockForTemporaryTable", + "Cases": [ + { + "SQL": "select * from t1 where a = 2 for update", + "Plan": [ + "Point_Get 1.00 root table:t1 handle:2" + ] + }, + { + "SQL": "select * from t1 where a in (1,2) for update", + "Plan": [ + "Batch_Point_Get 2.00 root table:t1 handle:[1 2], keep order:false, desc:false" + ] + }, + { + "SQL": "select c + 1 from t1 where a = 2 and c = 2 for update", + "Plan": [ + "Projection 0.00 root plus(test.t1.c, 1)->Column#4", + "└─Selection 0.00 root eq(test.t1.c, 2)", + " └─Point_Get 1.00 root table:t1 handle:2" + ] + }, + { + "SQL": "select c + 1 from t1 where a in (1,2) and c = 2 for update", + "Plan": [ + "Projection 0.00 root plus(test.t1.c, 1)->Column#4", + "└─Selection 0.00 root eq(test.t1.c, 2)", + " └─Batch_Point_Get 2.00 root table:t1 handle:[1 2], keep order:false, desc:false" + ] + } + ] } ]