From fd50df6e91d165e67a9e22cd67b3544d6225c6ac Mon Sep 17 00:00:00 2001 From: Hangjie Mo Date: Mon, 31 Jul 2023 19:07:08 +0800 Subject: [PATCH] planner, execute: Support `BatchPointGet` for Range and List Partition (#45646) close pingcap/tidb#45532 --- planner/core/casetest/partition/BUILD.bazel | 2 +- .../partition/integration_partition_test.go | 112 ++- .../integration_partition_suite_in.json | 71 +- .../integration_partition_suite_out.json | 683 ++++++++++++++++-- .../testdata/partition_pruner_out.json | 15 +- .../casetest/rule/rule_result_reorder_test.go | 4 +- .../ordered_result_mode_suite_out.json | 461 ++++++------ planner/core/find_best_task.go | 21 +- planner/core/point_get_plan.go | 54 +- planner/core/point_get_plan_test.go | 62 -- 10 files changed, 1051 insertions(+), 434 deletions(-) diff --git a/planner/core/casetest/partition/BUILD.bazel b/planner/core/casetest/partition/BUILD.bazel index b9521b90b2809..8af93ee5b92bb 100644 --- a/planner/core/casetest/partition/BUILD.bazel +++ b/planner/core/casetest/partition/BUILD.bazel @@ -10,7 +10,7 @@ go_test( ], data = glob(["testdata/**"]), flaky = True, - shard_count = 12, + shard_count = 13, deps = [ "//planner/core/internal", "//sessionctx/variable", diff --git a/planner/core/casetest/partition/integration_partition_test.go b/planner/core/casetest/partition/integration_partition_test.go index 9bc985338b449..ab19b3c476672 100644 --- a/planner/core/casetest/partition/integration_partition_test.go +++ b/planner/core/casetest/partition/integration_partition_test.go @@ -264,27 +264,33 @@ func TestBatchPointGetTablePartition(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop table if exists t1,t2,t3,t4,t5,t6") - tk.MustExec("create table t1(a int, b int, primary key(a,b) nonclustered) partition by hash(b) partitions 2") - tk.MustExec("insert into t1 values(1,1),(1,2),(2,1),(2,2)") + tk.MustExec("create table thash1(a int, b int, primary key(a,b) nonclustered) partition by hash(b) partitions 2") + tk.MustExec("insert into thash1 values(1,1),(1,2),(2,1),(2,2)") - tk.MustExec("create table t2(a int, b int, primary key(a,b) nonclustered) partition by range(b) (partition p0 values less than (2), partition p1 values less than maxvalue)") - tk.MustExec("insert into t2 values(1,1),(1,2),(2,1),(2,2)") + tk.MustExec("create table trange1(a int, b int, primary key(a,b) nonclustered) partition by range(b) (partition p0 values less than (2), partition p1 values less than maxvalue)") + tk.MustExec("insert into trange1 values(1,1),(1,2),(2,1),(2,2)") - tk.MustExec("create table t3(a int, b int, primary key(a,b)) partition by hash(b) partitions 2") - tk.MustExec("insert into t3 values(1,1),(1,2),(2,1),(2,2)") + tk.MustExec("create table tlist1(a int, b int, primary key(a,b) nonclustered) partition by list(b) (partition p0 values in (0, 1), partition p1 values in (2, 3))") + tk.MustExec("insert into tlist1 values(1,1),(1,2),(2,1),(2,2)") - tk.MustExec("create table t4(a int, b int, primary key(a,b)) partition by range(b) (partition p0 values less than (2), partition p1 values less than maxvalue)") - tk.MustExec("insert into t4 values(1,1),(1,2),(2,1),(2,2)") + tk.MustExec("create table thash2(a int, b int, primary key(a,b)) partition by hash(b) partitions 2") + tk.MustExec("insert into thash2 values(1,1),(1,2),(2,1),(2,2)") - tk.MustExec("create table t5(a int, b int, primary key(a)) partition by hash(a) partitions 2") - tk.MustExec("insert into t5 values(1,0),(2,0),(3,0),(4,0)") + tk.MustExec("create table trange2(a int, b int, primary key(a,b)) partition by range(b) (partition p0 values less than (2), partition p1 values less than maxvalue)") + tk.MustExec("insert into trange2 values(1,1),(1,2),(2,1),(2,2)") - tk.MustExec("create table t6(a int, b int, primary key(a)) partition by range(a) (partition p0 values less than (3), partition p1 values less than maxvalue)") - tk.MustExec("insert into t6 values(1,0),(2,0),(3,0),(4,0)") + tk.MustExec("create table tlist2(a int, b int, primary key(a,b)) partition by list(b) (partition p0 values in (0, 1), partition p1 values in (2, 3))") + tk.MustExec("insert into tlist2 values(1,1),(1,2),(2,1),(2,2)") - tk.MustExec(`analyze table t1, t2, t3, t4, t5, t6`) + tk.MustExec("create table thash3(a int, b int, primary key(a)) partition by hash(a) partitions 2") + tk.MustExec("insert into thash3 values(1,0),(2,0),(3,0),(4,0)") + + tk.MustExec("create table trange3(a int, b int, primary key(a)) partition by range(a) (partition p0 values less than (3), partition p1 values less than maxvalue)") + tk.MustExec("insert into trange3 values(1,0),(2,0),(3,0),(4,0)") + + tk.MustExec("create table tlist3(a int, b int, primary key(a)) partition by list(a) (partition p0 values in (0, 1, 2), partition p1 values in (3, 4, 5))") + tk.MustExec("insert into tlist3 values(1,0),(2,0),(3,0),(4,0)") var input []string var output []struct { @@ -301,20 +307,88 @@ func TestBatchPointGetTablePartition(t *testing.T) { output[i].SQL = tt tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") output[i].DynamicPlan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) - dynamicRes := testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) + dynamicQuery := tk.MustQuery(tt) + if !strings.Contains(tt, "order by") { + dynamicQuery = dynamicQuery.Sort() + } + dynamicRes := testdata.ConvertRowsToStrings(dynamicQuery.Rows()) tk.MustExec("set @@tidb_partition_prune_mode = 'static'") output[i].StaticPlan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows()) - staticRes := testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows()) - + staticQuery := tk.MustQuery(tt) + if !strings.Contains(tt, "order by") { + staticQuery = staticQuery.Sort() + } + staticRes := testdata.ConvertRowsToStrings(staticQuery.Rows()) require.Equal(t, dynamicRes, staticRes) output[i].Result = staticRes }) tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].DynamicPlan...)) - tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Result...)) + if strings.Contains(tt, "order by") { + tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...)) + } else { + tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Result...)) + } tk.MustExec("set @@tidb_partition_prune_mode = 'static'") tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].StaticPlan...)) - tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Result...)) + if strings.Contains(tt, "order by") { + tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...)) + } else { + tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Result...)) + } + } +} + +func TestBatchPointGetPartitionForAccessObject(t *testing.T) { + failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`) + defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune") + + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1(a int, b int, UNIQUE KEY (b)) PARTITION BY HASH(b) PARTITIONS 4") + tk.MustExec("insert into t1 values(1, 1), (2, 2), (3, 3), (4, 4)") + + tk.MustExec("CREATE TABLE t2 (id int primary key, name_id int) PARTITION BY LIST(id) (" + + "partition p0 values IN (1, 2), " + + "partition p1 values IN (3, 4), " + + "partition p3 values IN (5))") + tk.MustExec("insert into t2 values(1, 1), (2, 2), (3, 3), (4, 4)") + + tk.MustExec("CREATE TABLE t3 (id int primary key, name_id int) PARTITION BY LIST COLUMNS(id) (" + + "partition p0 values IN (1, 2), " + + "partition p1 values IN (3, 4), " + + "partition p3 values IN (5))") + tk.MustExec("insert into t3 values(1, 1), (2, 2), (3, 3), (4, 4)") + + tk.MustExec("CREATE TABLE t4 (id int, name_id int, unique key(id, name_id)) PARTITION BY LIST COLUMNS(id, name_id) (" + + "partition p0 values IN ((1, 1),(2, 2)), " + + "partition p1 values IN ((3, 3),(4, 4)), " + + "partition p3 values IN ((5, 5)))") + tk.MustExec("insert into t4 values(1, 1), (2, 2), (3, 3), (4, 4)") + + tk.MustExec("CREATE TABLE t5 (id int, name varchar(10), unique key(id, name)) PARTITION BY LIST COLUMNS(id, name) (" + + "partition p0 values IN ((1,'a'),(2,'b')), " + + "partition p1 values IN ((3,'c'),(4,'d')), " + + "partition p3 values IN ((5,'e')))") + tk.MustExec("insert into t5 values(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')") + + tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") + + var input []string + var output []struct { + SQL string + Plan []string + } + + integrationPartitionSuiteData := getIntegrationPartitionSuiteData() + integrationPartitionSuiteData.LoadTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + }) + tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...)) } } diff --git a/planner/core/casetest/partition/testdata/integration_partition_suite_in.json b/planner/core/casetest/partition/testdata/integration_partition_suite_in.json index d50e519920019..074180138a5d6 100644 --- a/planner/core/casetest/partition/testdata/integration_partition_suite_in.json +++ b/planner/core/casetest/partition/testdata/integration_partition_suite_in.json @@ -207,18 +207,65 @@ { "name": "TestBatchPointGetTablePartition", "cases": [ - "select * from t1 where a in (1,2) and b = 1", - "select * from t1 where a = 1 and b in (1,2)", - "select * from t2 where a in (1,2) and b = 1", - "select * from t2 where a = 1 and b in (1,2)", - "select * from t3 where a in (1,2) and b = 1", - "select * from t3 where a = 1 and b in (1,2)", - "select * from t4 where a in (1,2) and b = 1", - "select * from t4 where a = 1 and b in (1,2)", - "select * from t5 where a in (1,2) and 1 = 1", - "select * from t5 where a in (1,3) and 1 = 1", - "select * from t6 where a in (1,2) and 1 = 1", - "select * from t6 where a in (1,3) and 1 = 1" + "select * from thash1 where a in (1,2) and b = 1", + "select * from thash1 where a in (1,2) and b = 1 order by a", + "select * from thash1 where a in (1,2) and b = 1 order by a desc", + "select * from thash1 where a = 1 and b in (1,2)", + "select * from thash1 where a = 1 and b in (1,2) order by b", + "select * from thash1 where a = 1 and b in (1,2) order by b desc", + "select * from trange1 where a in (1,2) and b = 1", + "select * from trange1 where a in (1,2) and b = 1 order by a", + "select * from trange1 where a in (1,2) and b = 1 order by a desc", + "select * from trange1 where a = 1 and b in (1,2)", + "select * from trange1 where a = 1 and b in (1,2) order by b", + "select * from trange1 where a = 1 and b in (1,2) order by b desc", + "select * from tlist1 where a in (1,2) and b = 1", + "select * from tlist1 where a in (1,2) and b = 1 order by a", + "select * from tlist1 where a in (1,2) and b = 1 order by a desc", + "select * from tlist1 where a = 1 and b in (1,2)", + "select * from tlist1 where a = 1 and b in (1,2) order by b", + "select * from tlist1 where a = 1 and b in (1,2) order by b desc", + "select * from thash2 where a in (1,2) and b = 1", + "select * from thash2 where a in (1,2) and b = 1 order by a", + "select * from thash2 where a in (1,2) and b = 1 order by a desc", + "select * from thash2 where a = 1 and b in (1,2)", + "select * from thash2 where a = 1 and b in (1,2) order by b", + "select * from thash2 where a = 1 and b in (1,2) order by b desc", + "select * from trange2 where a in (1,2) and b = 1", + "select * from trange2 where a in (1,2) and b = 1 order by a", + "select * from trange2 where a in (1,2) and b = 1 order by a desc", + "select * from trange2 where a = 1 and b in (1,2)", + "select * from trange2 where a = 1 and b in (1,2) order by b", + "select * from trange2 where a = 1 and b in (1,2) order by b desc", + "select * from tlist2 where a in (1,2) and b = 1", + "select * from tlist2 where a in (1,2) and b = 1 order by a", + "select * from tlist2 where a in (1,2) and b = 1 order by a desc", + "select * from tlist2 where a = 1 and b in (1,2)", + "select * from tlist2 where a = 1 and b in (1,2) order by b", + "select * from tlist2 where a = 1 and b in (1,2) order by b desc", + "select * from thash3 where a in (1,2) and 1 = 1", + "select * from thash3 where a in (1,3) and 1 = 1", + "select * from thash3 where a in (1,3) and 1 = 1 order by a", + "select * from thash3 where a in (1,3) and 1 = 1 order by a desc", + "select * from trange3 where a in (1,2) and 1 = 1", + "select * from trange3 where a in (1,3) and 1 = 1", + "select * from trange3 where a in (1,3) and 1 = 1 order by a", + "select * from trange3 where a in (1,3) and 1 = 1 order by a desc", + "select * from tlist3 where a in (1,2) and 1 = 1", + "select * from tlist3 where a in (1,3) and 1 = 1", + "select * from tlist3 where a in (1,2) and 1 = 1 order by a", + "select * from tlist3 where a in (1,2) and 1 = 1 order by a desc" + ] + }, + { + "name": "TestBatchPointGetPartitionForAccessObject", + "cases": [ + "explain format='brief' select * from t1 where b in (1, 2)", + "explain format='brief' select * from t1 where b in (1, 2, 1)", + "explain format='brief' select * from t2 where id in (1, 3)", + "explain format='brief' select * from t3 where id in (1, 3)", + "explain format='brief' select * from t4 where (id, name_id) in ((1, 1), (3, 3))", + "explain format='brief' select * from t5 where (id, name) in ((1, 'a'), (3, 'c'))" ] } ] diff --git a/planner/core/casetest/partition/testdata/integration_partition_suite_out.json b/planner/core/casetest/partition/testdata/integration_partition_suite_out.json index 393511032cfd7..d822773f9f146 100644 --- a/planner/core/casetest/partition/testdata/integration_partition_suite_out.json +++ b/planner/core/casetest/partition/testdata/integration_partition_suite_out.json @@ -1672,12 +1672,12 @@ "Name": "TestBatchPointGetTablePartition", "Cases": [ { - "SQL": "select * from t1 where a in (1,2) and b = 1", + "SQL": "select * from thash1 where a in (1,2) and b = 1", "DynamicPlan": [ - "Batch_Point_Get 2.00 root table:t1, index:PRIMARY(a, b) keep order:false, desc:false" + "Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:false, desc:false" ], "StaticPlan": [ - "Batch_Point_Get 2.00 root table:t1, index:PRIMARY(a, b) keep order:false, desc:false" + "Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:false, desc:false" ], "Result": [ "1 1", @@ -1685,14 +1685,42 @@ ] }, { - "SQL": "select * from t1 where a = 1 and b in (1,2)", + "SQL": "select * from thash1 where a in (1,2) and b = 1 order by a", "DynamicPlan": [ - "Batch_Point_Get 2.00 root table:t1, index:PRIMARY(a, b) keep order:false, desc:false" + "IndexReader 2.00 root partition:p1 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:thash1, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:true, desc:false" + ], + "Result": [ + "1 1", + "2 1" + ] + }, + { + "SQL": "select * from thash1 where a in (1,2) and b = 1 order by a desc", + "DynamicPlan": [ + "IndexReader 2.00 root partition:p1 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:thash1, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:true, desc:true" + ], + "Result": [ + "2 1", + "1 1" + ] + }, + { + "SQL": "select * from thash1 where a = 1 and b in (1,2)", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:false, desc:false" ], "StaticPlan": [ "PartitionUnion 4.00 root ", - "├─Batch_Point_Get 2.00 root table:t1, index:PRIMARY(a, b) keep order:false, desc:false", - "└─Batch_Point_Get 2.00 root table:t1, index:PRIMARY(a, b) keep order:false, desc:false" + "├─Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:false, desc:false", + "└─Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:false, desc:false" ], "Result": [ "1 1", @@ -1700,14 +1728,60 @@ ] }, { - "SQL": "select * from t2 where a in (1,2) and b = 1", + "SQL": "select * from thash1 where a = 1 and b in (1,2) order by b", + "DynamicPlan": [ + "IndexReader 2.00 root partition:p0,p1 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:thash1, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Sort 4.00 root test.thash1.b", + "└─PartitionUnion 4.00 root ", + " ├─Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "1 2" + ] + }, + { + "SQL": "select * from thash1 where a = 1 and b in (1,2) order by b desc", + "DynamicPlan": [ + "IndexReader 2.00 root partition:p0,p1 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:thash1, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Sort 4.00 root test.thash1.b:desc", + "└─PartitionUnion 4.00 root ", + " ├─Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:thash1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 2", + "1 1" + ] + }, + { + "SQL": "select * from trange1 where a in (1,2) and b = 1", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "2 1" + ] + }, + { + "SQL": "select * from trange1 where a in (1,2) and b = 1 order by a", "DynamicPlan": [ "IndexReader 2.00 root partition:p0 index:IndexRangeScan", - "└─IndexRangeScan 2.00 cop[tikv] table:t2, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:false" + "└─IndexRangeScan 2.00 cop[tikv] table:trange1, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:true, stats:pseudo" ], "StaticPlan": [ - "IndexReader 2.00 root index:IndexRangeScan", - "└─IndexRangeScan 2.00 cop[tikv] table:t2, partition:p0, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:false" + "Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:true, desc:false" ], "Result": [ "1 1", @@ -1715,17 +1789,135 @@ ] }, { - "SQL": "select * from t2 where a = 1 and b in (1,2)", + "SQL": "select * from trange1 where a in (1,2) and b = 1 order by a desc", + "DynamicPlan": [ + "IndexReader 2.00 root partition:p0 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:trange1, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:true, desc:true" + ], + "Result": [ + "2 1", + "1 1" + ] + }, + { + "SQL": "select * from trange1 where a = 1 and b in (1,2)", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "StaticPlan": [ + "PartitionUnion 4.00 root ", + "├─Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:false, desc:false", + "└─Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "1 2" + ] + }, + { + "SQL": "select * from trange1 where a = 1 and b in (1,2) order by b", + "DynamicPlan": [ + "IndexReader 2.00 root partition:all index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:trange1, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Sort 4.00 root test.trange1.b", + "└─PartitionUnion 4.00 root ", + " ├─Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "1 2" + ] + }, + { + "SQL": "select * from trange1 where a = 1 and b in (1,2) order by b desc", "DynamicPlan": [ "IndexReader 2.00 root partition:all index:IndexRangeScan", - "└─IndexRangeScan 2.00 cop[tikv] table:t2, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:false" + "└─IndexRangeScan 2.00 cop[tikv] table:trange1, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Sort 4.00 root test.trange1.b:desc", + "└─PartitionUnion 4.00 root ", + " ├─Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:trange1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 2", + "1 1" + ] + }, + { + "SQL": "select * from tlist1 where a in (1,2) and b = 1", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "2 1" + ] + }, + { + "SQL": "select * from tlist1 where a in (1,2) and b = 1 order by a", + "DynamicPlan": [ + "IndexReader 2.00 root partition:p0 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:tlist1, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:true, desc:false" + ], + "Result": [ + "1 1", + "2 1" + ] + }, + { + "SQL": "select * from tlist1 where a in (1,2) and b = 1 order by a desc", + "DynamicPlan": [ + "IndexReader 2.00 root partition:p0 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:tlist1, index:PRIMARY(a, b) range:[1 1,1 1], [2 1,2 1], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:true, desc:true" + ], + "Result": [ + "2 1", + "1 1" + ] + }, + { + "SQL": "select * from tlist1 where a = 1 and b in (1,2)", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:false, desc:false" ], "StaticPlan": [ "PartitionUnion 4.00 root ", - "├─IndexReader 2.00 root index:IndexRangeScan", - "│ └─IndexRangeScan 2.00 cop[tikv] table:t2, partition:p0, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:false", - "└─IndexReader 2.00 root index:IndexRangeScan", - " └─IndexRangeScan 2.00 cop[tikv] table:t2, partition:p1, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:false" + "├─Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:false, desc:false", + "└─Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "1 2" + ] + }, + { + "SQL": "select * from tlist1 where a = 1 and b in (1,2) order by b", + "DynamicPlan": [ + "IndexReader 2.00 root partition:p0,p1 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:tlist1, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Sort 4.00 root test.tlist1.b", + "└─PartitionUnion 4.00 root ", + " ├─Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:false, desc:false" ], "Result": [ "1 1", @@ -1733,12 +1925,29 @@ ] }, { - "SQL": "select * from t3 where a in (1,2) and b = 1", + "SQL": "select * from tlist1 where a = 1 and b in (1,2) order by b desc", + "DynamicPlan": [ + "IndexReader 2.00 root partition:p0,p1 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:tlist1, index:PRIMARY(a, b) range:[1 1,1 1], [1 2,1 2], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Sort 4.00 root test.tlist1.b:desc", + "└─PartitionUnion 4.00 root ", + " ├─Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:tlist1, index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 2", + "1 1" + ] + }, + { + "SQL": "select * from thash2 where a in (1,2) and b = 1", "DynamicPlan": [ - "Batch_Point_Get 2.00 root table:t3, clustered index:PRIMARY(a, b) keep order:false, desc:false" + "Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:false, desc:false" ], "StaticPlan": [ - "Batch_Point_Get 2.00 root table:t3, clustered index:PRIMARY(a, b) keep order:false, desc:false" + "Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:false, desc:false" ], "Result": [ "1 1", @@ -1746,14 +1955,59 @@ ] }, { - "SQL": "select * from t3 where a = 1 and b in (1,2)", + "SQL": "select * from thash2 where a in (1,2) and b = 1 order by a", "DynamicPlan": [ - "Batch_Point_Get 2.00 root table:t3, clustered index:PRIMARY(a, b) keep order:false, desc:false" + "TableReader 2.00 root partition:p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:thash2 range:[1 1,1 1], [2 1,2 1], keep order:true, stats:pseudo" ], "StaticPlan": [ - "PartitionUnion 2.00 root ", - "├─Batch_Point_Get 2.00 root table:t3, clustered index:PRIMARY(a, b) keep order:false, desc:false", - "└─Batch_Point_Get 2.00 root table:t3, clustered index:PRIMARY(a, b) keep order:false, desc:false" + "Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:true, desc:false" + ], + "Result": [ + "1 1", + "2 1" + ] + }, + { + "SQL": "select * from thash2 where a in (1,2) and b = 1 order by a desc", + "DynamicPlan": [ + "TableReader 2.00 root partition:p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:thash2 range:[1 1,1 1], [2 1,2 1], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:true, desc:true" + ], + "Result": [ + "2 1", + "1 1" + ] + }, + { + "SQL": "select * from thash2 where a = 1 and b in (1,2)", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "StaticPlan": [ + "PartitionUnion 0.04 root ", + "├─Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:false, desc:false", + "└─Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "1 2" + ] + }, + { + "SQL": "select * from thash2 where a = 1 and b in (1,2) order by b", + "DynamicPlan": [ + "TableReader 2.00 root partition:p0,p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:thash2 range:[1 1,1 1], [1 2,1 2], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Sort 0.04 root test.thash2.b", + "└─PartitionUnion 0.04 root ", + " ├─Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:false, desc:false" ], "Result": [ "1 1", @@ -1761,14 +2015,43 @@ ] }, { - "SQL": "select * from t4 where a in (1,2) and b = 1", + "SQL": "select * from thash2 where a = 1 and b in (1,2) order by b desc", + "DynamicPlan": [ + "TableReader 2.00 root partition:p0,p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:thash2 range:[1 1,1 1], [1 2,1 2], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Sort 0.04 root test.thash2.b:desc", + "└─PartitionUnion 0.04 root ", + " ├─Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:thash2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 2", + "1 1" + ] + }, + { + "SQL": "select * from trange2 where a in (1,2) and b = 1", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "2 1" + ] + }, + { + "SQL": "select * from trange2 where a in (1,2) and b = 1 order by a", "DynamicPlan": [ "TableReader 2.00 root partition:p0 data:TableRangeScan", - "└─TableRangeScan 2.00 cop[tikv] table:t4 range:[1 1,1 1], [2 1,2 1], keep order:false" + "└─TableRangeScan 2.00 cop[tikv] table:trange2 range:[1 1,1 1], [2 1,2 1], keep order:true, stats:pseudo" ], "StaticPlan": [ - "TableReader 2.00 root data:TableRangeScan", - "└─TableRangeScan 2.00 cop[tikv] table:t4, partition:p0 range:[1 1,1 1], [2 1,2 1], keep order:false" + "Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:true, desc:false" ], "Result": [ "1 1", @@ -1776,17 +2059,45 @@ ] }, { - "SQL": "select * from t4 where a = 1 and b in (1,2)", + "SQL": "select * from trange2 where a in (1,2) and b = 1 order by a desc", + "DynamicPlan": [ + "TableReader 2.00 root partition:p0 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:trange2 range:[1 1,1 1], [2 1,2 1], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:true, desc:true" + ], + "Result": [ + "2 1", + "1 1" + ] + }, + { + "SQL": "select * from trange2 where a = 1 and b in (1,2)", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "StaticPlan": [ + "PartitionUnion 0.04 root ", + "├─Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:false, desc:false", + "└─Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "1 2" + ] + }, + { + "SQL": "select * from trange2 where a = 1 and b in (1,2) order by b", "DynamicPlan": [ "TableReader 2.00 root partition:all data:TableRangeScan", - "└─TableRangeScan 2.00 cop[tikv] table:t4 range:[1 1,1 1], [1 2,1 2], keep order:false" + "└─TableRangeScan 2.00 cop[tikv] table:trange2 range:[1 1,1 1], [1 2,1 2], keep order:true, stats:pseudo" ], "StaticPlan": [ - "PartitionUnion 2.00 root ", - "├─TableReader 2.00 root data:TableRangeScan", - "│ └─TableRangeScan 2.00 cop[tikv] table:t4, partition:p0 range:[1 1,1 1], [1 2,1 2], keep order:false", - "└─TableReader 2.00 root data:TableRangeScan", - " └─TableRangeScan 2.00 cop[tikv] table:t4, partition:p1 range:[1 1,1 1], [1 2,1 2], keep order:false" + "Sort 0.04 root test.trange2.b", + "└─PartitionUnion 0.04 root ", + " ├─Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:false, desc:false" ], "Result": [ "1 1", @@ -1794,14 +2105,121 @@ ] }, { - "SQL": "select * from t5 where a in (1,2) and 1 = 1", + "SQL": "select * from trange2 where a = 1 and b in (1,2) order by b desc", "DynamicPlan": [ - "Batch_Point_Get 2.00 root table:t5 handle:[1 2], keep order:false, desc:false" + "TableReader 2.00 root partition:all data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:trange2 range:[1 1,1 1], [1 2,1 2], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Sort 0.04 root test.trange2.b:desc", + "└─PartitionUnion 0.04 root ", + " ├─Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:trange2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 2", + "1 1" + ] + }, + { + "SQL": "select * from tlist2 where a in (1,2) and b = 1", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "2 1" + ] + }, + { + "SQL": "select * from tlist2 where a in (1,2) and b = 1 order by a", + "DynamicPlan": [ + "TableReader 2.00 root partition:p0 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:tlist2 range:[1 1,1 1], [2 1,2 1], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:true, desc:false" + ], + "Result": [ + "1 1", + "2 1" + ] + }, + { + "SQL": "select * from tlist2 where a in (1,2) and b = 1 order by a desc", + "DynamicPlan": [ + "TableReader 2.00 root partition:p0 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:tlist2 range:[1 1,1 1], [2 1,2 1], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:true, desc:true" + ], + "Result": [ + "2 1", + "1 1" + ] + }, + { + "SQL": "select * from tlist2 where a = 1 and b in (1,2)", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "StaticPlan": [ + "PartitionUnion 0.04 root ", + "├─Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:false, desc:false", + "└─Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "1 2" + ] + }, + { + "SQL": "select * from tlist2 where a = 1 and b in (1,2) order by b", + "DynamicPlan": [ + "TableReader 2.00 root partition:p0,p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:tlist2 range:[1 1,1 1], [1 2,1 2], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Sort 0.04 root test.tlist2.b", + "└─PartitionUnion 0.04 root ", + " ├─Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 1", + "1 2" + ] + }, + { + "SQL": "select * from tlist2 where a = 1 and b in (1,2) order by b desc", + "DynamicPlan": [ + "TableReader 2.00 root partition:p0,p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:tlist2 range:[1 1,1 1], [1 2,1 2], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Sort 0.04 root test.tlist2.b:desc", + "└─PartitionUnion 0.04 root ", + " ├─Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:tlist2, clustered index:PRIMARY(a, b) keep order:false, desc:false" + ], + "Result": [ + "1 2", + "1 1" + ] + }, + { + "SQL": "select * from thash3 where a in (1,2) and 1 = 1", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:thash3 handle:[1 2], keep order:false, desc:false" ], "StaticPlan": [ "PartitionUnion 4.00 root ", - "├─Batch_Point_Get 2.00 root table:t5 handle:[1 2], keep order:false, desc:false", - "└─Batch_Point_Get 2.00 root table:t5 handle:[1 2], keep order:false, desc:false" + "├─Batch_Point_Get 2.00 root table:thash3 handle:[1 2], keep order:false, desc:false", + "└─Batch_Point_Get 2.00 root table:thash3 handle:[1 2], keep order:false, desc:false" ], "Result": [ "1 0", @@ -1809,12 +2227,12 @@ ] }, { - "SQL": "select * from t5 where a in (1,3) and 1 = 1", + "SQL": "select * from thash3 where a in (1,3) and 1 = 1", "DynamicPlan": [ - "Batch_Point_Get 2.00 root table:t5 handle:[1 3], keep order:false, desc:false" + "Batch_Point_Get 2.00 root table:thash3 handle:[1 3], keep order:false, desc:false" ], "StaticPlan": [ - "Batch_Point_Get 2.00 root table:t5 handle:[1 3], keep order:false, desc:false" + "Batch_Point_Get 2.00 root table:thash3 handle:[1 3], keep order:false, desc:false" ], "Result": [ "1 0", @@ -1822,14 +2240,40 @@ ] }, { - "SQL": "select * from t6 where a in (1,2) and 1 = 1", + "SQL": "select * from thash3 where a in (1,3) and 1 = 1 order by a", "DynamicPlan": [ - "TableReader 2.00 root partition:p0 data:TableRangeScan", - "└─TableRangeScan 2.00 cop[tikv] table:t6 range:[1,1], [2,2], keep order:false" + "TableReader 2.00 root partition:p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:thash3 range:[1,1], [3,3], keep order:true, stats:pseudo" ], "StaticPlan": [ - "TableReader 2.00 root data:TableRangeScan", - "└─TableRangeScan 2.00 cop[tikv] table:t6, partition:p0 range:[1,1], [2,2], keep order:false" + "Batch_Point_Get 2.00 root table:thash3 handle:[1 3], keep order:true, desc:false" + ], + "Result": [ + "1 0", + "3 0" + ] + }, + { + "SQL": "select * from thash3 where a in (1,3) and 1 = 1 order by a desc", + "DynamicPlan": [ + "TableReader 2.00 root partition:p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:thash3 range:[1,1], [3,3], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:thash3 handle:[1 3], keep order:true, desc:true" + ], + "Result": [ + "3 0", + "1 0" + ] + }, + { + "SQL": "select * from trange3 where a in (1,2) and 1 = 1", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:trange3 handle:[1 2], keep order:false, desc:false" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:trange3 handle:[1 2], keep order:false, desc:false" ], "Result": [ "1 0", @@ -1837,22 +2281,153 @@ ] }, { - "SQL": "select * from t6 where a in (1,3) and 1 = 1", + "SQL": "select * from trange3 where a in (1,3) and 1 = 1", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:trange3 handle:[1 3], keep order:false, desc:false" + ], + "StaticPlan": [ + "PartitionUnion 4.00 root ", + "├─Batch_Point_Get 2.00 root table:trange3 handle:[1 3], keep order:false, desc:false", + "└─Batch_Point_Get 2.00 root table:trange3 handle:[1 3], keep order:false, desc:false" + ], + "Result": [ + "1 0", + "3 0" + ] + }, + { + "SQL": "select * from trange3 where a in (1,3) and 1 = 1 order by a", + "DynamicPlan": [ + "TableReader 2.00 root partition:all data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:trange3 range:[1,1], [3,3], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Sort 4.00 root test.trange3.a", + "└─PartitionUnion 4.00 root ", + " ├─Batch_Point_Get 2.00 root table:trange3 handle:[1 3], keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:trange3 handle:[1 3], keep order:false, desc:false" + ], + "Result": [ + "1 0", + "3 0" + ] + }, + { + "SQL": "select * from trange3 where a in (1,3) and 1 = 1 order by a desc", "DynamicPlan": [ "TableReader 2.00 root partition:all data:TableRangeScan", - "└─TableRangeScan 2.00 cop[tikv] table:t6 range:[1,1], [3,3], keep order:false" + "└─TableRangeScan 2.00 cop[tikv] table:trange3 range:[1,1], [3,3], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Sort 4.00 root test.trange3.a:desc", + "└─PartitionUnion 4.00 root ", + " ├─Batch_Point_Get 2.00 root table:trange3 handle:[1 3], keep order:false, desc:false", + " └─Batch_Point_Get 2.00 root table:trange3 handle:[1 3], keep order:false, desc:false" + ], + "Result": [ + "3 0", + "1 0" + ] + }, + { + "SQL": "select * from tlist3 where a in (1,2) and 1 = 1", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:tlist3 handle:[1 2], keep order:false, desc:false" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:tlist3 handle:[1 2], keep order:false, desc:false" + ], + "Result": [ + "1 0", + "2 0" + ] + }, + { + "SQL": "select * from tlist3 where a in (1,3) and 1 = 1", + "DynamicPlan": [ + "Batch_Point_Get 2.00 root table:tlist3 handle:[1 3], keep order:false, desc:false" ], "StaticPlan": [ "PartitionUnion 4.00 root ", - "├─TableReader 2.00 root data:TableRangeScan", - "│ └─TableRangeScan 2.00 cop[tikv] table:t6, partition:p0 range:[1,1], [3,3], keep order:false", - "└─TableReader 2.00 root data:TableRangeScan", - " └─TableRangeScan 2.00 cop[tikv] table:t6, partition:p1 range:[1,1], [3,3], keep order:false" + "├─Batch_Point_Get 2.00 root table:tlist3 handle:[1 3], keep order:false, desc:false", + "└─Batch_Point_Get 2.00 root table:tlist3 handle:[1 3], keep order:false, desc:false" ], "Result": [ "1 0", "3 0" ] + }, + { + "SQL": "select * from tlist3 where a in (1,2) and 1 = 1 order by a", + "DynamicPlan": [ + "TableReader 2.00 root partition:p0 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:tlist3 range:[1,1], [2,2], keep order:true, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:tlist3 handle:[1 2], keep order:true, desc:false" + ], + "Result": [ + "1 0", + "2 0" + ] + }, + { + "SQL": "select * from tlist3 where a in (1,2) and 1 = 1 order by a desc", + "DynamicPlan": [ + "TableReader 2.00 root partition:p0 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:tlist3 range:[1,1], [2,2], keep order:true, desc, stats:pseudo" + ], + "StaticPlan": [ + "Batch_Point_Get 2.00 root table:tlist3 handle:[1 2], keep order:true, desc:true" + ], + "Result": [ + "2 0", + "1 0" + ] + } + ] + }, + { + "Name": "TestBatchPointGetPartitionForAccessObject", + "Cases": [ + { + "SQL": "explain format='brief' select * from t1 where b in (1, 2)", + "Plan": [ + "Batch_Point_Get 2.00 root table:t1, partition:p1,p2, index:b(b) keep order:false, desc:false" + ] + }, + { + "SQL": "explain format='brief' select * from t1 where b in (1, 2, 1)", + "Plan": [ + "Batch_Point_Get 3.00 root table:t1, partition:p1,p2, index:b(b) keep order:false, desc:false" + ] + }, + { + "SQL": "explain format='brief' select * from t2 where id in (1, 3)", + "Plan": [ + "Batch_Point_Get 2.00 root table:t2, partition:p0,p1 handle:[1 3], keep order:false, desc:false" + ] + }, + { + "SQL": "explain format='brief' select * from t3 where id in (1, 3)", + "Plan": [ + "TableReader 2.00 root partition:p0,p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:t3 range:[1,1], [3,3], keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format='brief' select * from t4 where (id, name_id) in ((1, 1), (3, 3))", + "Plan": [ + "IndexReader 2.00 root partition:p0,p1 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:t4, index:id(id, name_id) range:[1 1,1 1], [3 3,3 3], keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format='brief' select * from t5 where (id, name) in ((1, 'a'), (3, 'c'))", + "Plan": [ + "IndexReader 2.00 root partition:p0,p1 index:IndexRangeScan", + "└─IndexRangeScan 2.00 cop[tikv] table:t5, index:id(id, name) range:[1 \"a\",1 \"a\"], [3 \"c\",3 \"c\"], keep order:false, stats:pseudo" + ] } ] } diff --git a/planner/core/casetest/partition/testdata/partition_pruner_out.json b/planner/core/casetest/partition/testdata/partition_pruner_out.json index d454d8422965b..aaa35b45335dc 100644 --- a/planner/core/casetest/partition/testdata/partition_pruner_out.json +++ b/planner/core/casetest/partition/testdata/partition_pruner_out.json @@ -740,9 +740,8 @@ ], "Plan": [ "HashJoin 2.50 root inner join, equal:[eq(test_partition.t4.id, test_partition.t5.id)]", - "├─TableReader(Build) 2.00 root partition:p0 data:Selection", - "│ └─Selection 2.00 cop[tikv] not(isnull(test_partition.t4.id))", - "│ └─TableRangeScan 2.00 cop[tikv] table:t4 range:[1,1], [3,3], keep order:false, stats:pseudo", + "├─Selection(Build) 2.00 root not(isnull(test_partition.t4.id))", + "│ └─Batch_Point_Get 2.00 root table:t4 handle:[1 3], keep order:false, desc:false", "└─IndexLookUp(Probe) 4.00 root partition:p0,p1 ", " ├─IndexRangeScan(Build) 4.00 cop[tikv] table:t5, index:a(a, b) range:[1 1,1 1], [1 6,1 6], [6 1,6 1], [6 6,6 6], keep order:false, stats:pseudo", " └─Selection(Probe) 4.00 cop[tikv] not(isnull(test_partition.t5.id))", @@ -756,12 +755,10 @@ ], "Plan": [ "HashJoin 2.50 root inner join, equal:[eq(test_partition.t4.id, test_partition.t4.id)]", - "├─TableReader(Build) 2.00 root partition:p0 data:Selection", - "│ └─Selection 2.00 cop[tikv] not(isnull(test_partition.t4.id))", - "│ └─TableRangeScan 2.00 cop[tikv] table:t1 range:[1,1], [4,4], keep order:false, stats:pseudo", - "└─TableReader(Probe) 4.00 root partition:p0,p1 data:Selection", - " └─Selection 4.00 cop[tikv] not(isnull(test_partition.t4.id))", - " └─TableRangeScan 4.00 cop[tikv] table:t2 range:[1,1], [3,3], [9,9], [100,100], keep order:false, stats:pseudo" + "├─Selection(Build) 2.00 root not(isnull(test_partition.t4.id))", + "│ └─Batch_Point_Get 2.00 root table:t4 handle:[1 4], keep order:false, desc:false", + "└─Selection(Probe) 4.00 root not(isnull(test_partition.t4.id))", + " └─Batch_Point_Get 4.00 root table:t4 handle:[1 3 9 100], keep order:false, desc:false" ] }, { diff --git a/planner/core/casetest/rule/rule_result_reorder_test.go b/planner/core/casetest/rule/rule_result_reorder_test.go index 8c72a37db0f0a..f2b1790690d97 100644 --- a/planner/core/casetest/rule/rule_result_reorder_test.go +++ b/planner/core/casetest/rule/rule_result_reorder_test.go @@ -34,9 +34,9 @@ func runTestData(t *testing.T, tk *testkit.TestKit, name string) { require.Equal(t, len(input), len(output)) for i := range input { testdata.OnRecord(func() { - output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + input[i]).Rows()) + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain FORMAT='brief' " + input[i]).Rows()) }) - tk.MustQuery("explain " + input[i]).Check(testkit.Rows(output[i].Plan...)) + tk.MustQuery("explain FORMAT='brief' " + input[i]).Check(testkit.Rows(output[i].Plan...)) } } diff --git a/planner/core/casetest/rule/testdata/ordered_result_mode_suite_out.json b/planner/core/casetest/rule/testdata/ordered_result_mode_suite_out.json index 2eb50fa2ea4de..b1c673cf7eec2 100644 --- a/planner/core/casetest/rule/testdata/ordered_result_mode_suite_out.json +++ b/planner/core/casetest/rule/testdata/ordered_result_mode_suite_out.json @@ -4,109 +4,109 @@ "Cases": [ { "Plan": [ - "TableReader_10 10000.00 root data:TableFullScan_9", - "└─TableFullScan_9 10000.00 cop[tikv] table:t keep order:true, stats:pseudo" + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:t keep order:true, stats:pseudo" ] }, { "Plan": [ - "IndexReader_10 10000.00 root index:IndexFullScan_9", - "└─IndexFullScan_9 10000.00 cop[tikv] table:t, index:b(b) keep order:true, stats:pseudo" + "IndexReader 10000.00 root index:IndexFullScan", + "└─IndexFullScan 10000.00 cop[tikv] table:t, index:b(b) keep order:true, stats:pseudo" ] }, { "Plan": [ - "Sort_5 10000.00 root test.t.a", - "└─IndexReader_8 10000.00 root index:IndexFullScan_7", - " └─IndexFullScan_7 10000.00 cop[tikv] table:t, index:b(b) keep order:false, stats:pseudo" + "Sort 10000.00 root test.t.a", + "└─IndexReader 10000.00 root index:IndexFullScan", + " └─IndexFullScan 10000.00 cop[tikv] table:t, index:b(b) keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_5 10000.00 root test.t.b, test.t.c", - "└─IndexLookUp_9 10000.00 root ", - " ├─IndexFullScan_7(Build) 10000.00 cop[tikv] table:t, index:b(b) keep order:false, stats:pseudo", - " └─TableRowIDScan_8(Probe) 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + "Sort 10000.00 root test.t.b, test.t.c", + "└─IndexLookUp 10000.00 root ", + " ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, index:b(b) keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_5 10000.00 root test.t.b, test.t.c", - "└─TableReader_8 10000.00 root data:TableFullScan_7", - " └─TableFullScan_7 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + "Sort 10000.00 root test.t.b, test.t.c", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_6 8000.00 root Column#5, Column#6", - "└─HashAgg_12 8000.00 root group by:test.t.d, funcs:min(Column#7)->Column#5, funcs:max(Column#8)->Column#6", - " └─TableReader_13 8000.00 root data:HashAgg_8", - " └─HashAgg_8 8000.00 cop[tikv] group by:test.t.d, funcs:min(test.t.b)->Column#7, funcs:max(test.t.c)->Column#8", - " └─TableFullScan_11 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + "Sort 8000.00 root Column#5, Column#6", + "└─HashAgg 8000.00 root group by:test.t.d, funcs:min(Column#7)->Column#5, funcs:max(Column#8)->Column#6", + " └─TableReader 8000.00 root data:HashAgg", + " └─HashAgg 8000.00 cop[tikv] group by:test.t.d, funcs:min(test.t.b)->Column#7, funcs:max(test.t.c)->Column#8", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_7 10000.00 root test.t.b, test.t.c", - "└─TableReader_10 10000.00 root data:TableFullScan_9", - " └─TableFullScan_9 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + "Sort 10000.00 root test.t.b, test.t.c", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "TopN_8 10.00 root test.t.a, offset:0, count:10", - "└─IndexLookUp_17 10.00 root ", - " ├─TopN_16(Build) 10.00 cop[tikv] test.t.a, offset:0, count:10", - " │ └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:b(b) keep order:false, stats:pseudo", - " └─TableRowIDScan_15(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo" + "TopN 10.00 root test.t.a, offset:0, count:10", + "└─IndexLookUp 10.00 root ", + " ├─TopN(Build) 10.00 cop[tikv] test.t.a, offset:0, count:10", + " │ └─IndexFullScan 10000.00 cop[tikv] table:t, index:b(b) keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "Limit_11 10.00 root offset:0, count:10", - "└─TableReader_21 10.00 root data:Limit_20", - " └─Limit_20 10.00 cop[tikv] offset:0, count:10", - " └─TableFullScan_19 10.00 cop[tikv] table:t keep order:true, stats:pseudo" + "Limit 10.00 root offset:0, count:10", + "└─TableReader 10.00 root data:Limit", + " └─Limit 10.00 cop[tikv] offset:0, count:10", + " └─TableFullScan 10.00 cop[tikv] table:t keep order:true, stats:pseudo" ] }, { "Plan": [ - "IndexReader_11 10000.00 root index:IndexFullScan_10", - "└─IndexFullScan_10 10000.00 cop[tikv] table:t, index:b(b) keep order:true, stats:pseudo" + "IndexReader 10000.00 root index:IndexFullScan", + "└─IndexFullScan 10000.00 cop[tikv] table:t, index:b(b) keep order:true, stats:pseudo" ] }, { "Plan": [ - "Sort_4 10000.00 root test.t.b, test.t.c, test.t.d", - "└─IndexLookUp_9 10000.00 root ", - " ├─IndexFullScan_7(Build) 10000.00 cop[tikv] table:t, index:b(b) keep order:false, stats:pseudo", - " └─TableRowIDScan_8(Probe) 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + "Sort 10000.00 root test.t.b, test.t.c, test.t.d", + "└─IndexLookUp 10000.00 root ", + " ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, index:b(b) keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_9 12500.00 root test.t.a, test.t.a", - "└─MergeJoin_11 12500.00 root inner join, left key:test.t.a, right key:test.t.a", - " ├─TableReader_35(Build) 10000.00 root data:TableFullScan_34", - " │ └─TableFullScan_34 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", - " └─TableReader_33(Probe) 10000.00 root data:TableFullScan_32", - " └─TableFullScan_32 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" + "Sort 12500.00 root test.t.a, test.t.a", + "└─MergeJoin 12500.00 root inner join, left key:test.t.a, right key:test.t.a", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" ] }, { "Plan": [ - "Projection_5 3333.33 root test.t.b", - "└─TableReader_11 3333.33 root data:TableRangeScan_10", - " └─TableRangeScan_10 3333.33 cop[tikv] table:t range:(0,+inf], keep order:true, stats:pseudo" + "Projection 3333.33 root test.t.b", + "└─TableReader 3333.33 root data:TableRangeScan", + " └─TableRangeScan 3333.33 cop[tikv] table:t range:(0,+inf], keep order:true, stats:pseudo" ] }, { "Plan": [ - "Projection_7 1.00 root test.t.b", - "└─Limit_12 1.00 root offset:0, count:1", - " └─TableReader_22 1.00 root data:Limit_21", - " └─Limit_21 1.00 cop[tikv] offset:0, count:1", - " └─TableRangeScan_20 1.00 cop[tikv] table:t range:(0,+inf], keep order:true, stats:pseudo" + "Projection 1.00 root test.t.b", + "└─Limit 1.00 root offset:0, count:1", + " └─TableReader 1.00 root data:Limit", + " └─Limit 1.00 cop[tikv] offset:0, count:1", + " └─TableRangeScan 1.00 cop[tikv] table:t range:(0,+inf], keep order:true, stats:pseudo" ] } ] @@ -116,63 +116,63 @@ "Cases": [ { "Plan": [ - "Insert_1 N/A root N/A", - "└─TableReader_7 10000.00 root data:TableFullScan_6", - " └─TableFullScan_6 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + "Insert N/A root N/A", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "Insert_1 N/A root N/A", - "└─TableReader_8 3333.33 root data:TableRangeScan_7", - " └─TableRangeScan_7 3333.33 cop[tikv] table:t range:(1,+inf], keep order:false, stats:pseudo" + "Insert N/A root N/A", + "└─TableReader 3333.33 root data:TableRangeScan", + " └─TableRangeScan 3333.33 cop[tikv] table:t range:(1,+inf], keep order:false, stats:pseudo" ] }, { "Plan": [ - "Insert_1 N/A root N/A", - "└─Projection_9 12500.00 root test.t.a, test.t.b, plus(test.t.c, test.t.c)->Column#10", - " └─MergeJoin_10 12500.00 root inner join, left key:test.t.a, right key:test.t.a", - " ├─TableReader_34(Build) 10000.00 root data:TableFullScan_33", - " │ └─TableFullScan_33 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", - " └─TableReader_32(Probe) 10000.00 root data:TableFullScan_31", - " └─TableFullScan_31 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" + "Insert N/A root N/A", + "└─Projection 12500.00 root test.t.a, test.t.b, plus(test.t.c, test.t.c)->Column#10", + " └─MergeJoin 12500.00 root inner join, left key:test.t.a, right key:test.t.a", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" ] }, { "Plan": [ - "Insert_1 N/A root N/A", - "└─Projection_7 10000.00 root test.t.a->Column#7, test.t.b->Column#8, cast(test.t.c, decimal(32,0) BINARY)->Column#9", - " └─TableReader_9 10000.00 root data:TableFullScan_8", - " └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + "Insert N/A root N/A", + "└─Projection 10000.00 root test.t.a->Column#7, test.t.b->Column#8, cast(test.t.c, decimal(32,0) BINARY)->Column#9", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "Delete_3 N/A root N/A", - "└─TableReader_6 10000.00 root data:TableFullScan_5", - " └─TableFullScan_5 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + "Delete N/A root N/A", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "Delete_4 N/A root N/A", - "└─TableReader_7 3333.33 root data:TableRangeScan_6", - " └─TableRangeScan_6 3333.33 cop[tikv] table:t range:(1,+inf], keep order:false, stats:pseudo" + "Delete N/A root N/A", + "└─TableReader 3333.33 root data:TableRangeScan", + " └─TableRangeScan 3333.33 cop[tikv] table:t range:(1,+inf], keep order:false, stats:pseudo" ] }, { "Plan": [ - "Update_3 N/A root N/A", - "└─TableReader_6 10000.00 root data:TableFullScan_5", - " └─TableFullScan_5 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + "Update N/A root N/A", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] }, { "Plan": [ - "Update_4 N/A root N/A", - "└─TableReader_7 3333.33 root data:TableRangeScan_6", - " └─TableRangeScan_6 3333.33 cop[tikv] table:t range:(1,+inf], keep order:false, stats:pseudo" + "Update N/A root N/A", + "└─TableReader 3333.33 root data:TableRangeScan", + " └─TableRangeScan 3333.33 cop[tikv] table:t range:(1,+inf], keep order:false, stats:pseudo" ] } ] @@ -182,102 +182,102 @@ "Cases": [ { "Plan": [ - "Sort_11 9990.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─MergeJoin_13 9990.00 root inner join, left key:test.t1.a, right key:test.t2.b", - " ├─StreamAgg_30(Build) 7992.00 root group by:test.t2.b, funcs:firstrow(test.t2.b)->test.t2.b", - " │ └─IndexReader_31 7992.00 root index:StreamAgg_27", - " │ └─StreamAgg_27 7992.00 cop[tikv] group by:test.t2.b, ", - " │ └─IndexFullScan_29 9990.00 cop[tikv] table:t2, index:b(b) keep order:true, stats:pseudo", - " └─TableReader_26(Probe) 10000.00 root data:TableFullScan_25", - " └─TableFullScan_25 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" + "Sort 9990.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─MergeJoin 9990.00 root inner join, left key:test.t1.a, right key:test.t2.b", + " ├─StreamAgg(Build) 7992.00 root group by:test.t2.b, funcs:firstrow(test.t2.b)->test.t2.b", + " │ └─IndexReader 7992.00 root index:StreamAgg", + " │ └─StreamAgg 7992.00 cop[tikv] group by:test.t2.b, ", + " │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:b(b) keep order:true, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" ] }, { "Plan": [ - "Sort_9 8000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─HashJoin_11 8000.00 root Null-aware anti semi join, equal:[eq(test.t1.a, test.t2.b)]", - " ├─IndexReader_17(Build) 10000.00 root index:IndexFullScan_16", - " │ └─IndexFullScan_16 10000.00 cop[tikv] table:t2, index:b(b) keep order:false, stats:pseudo", - " └─TableReader_13(Probe) 10000.00 root data:TableFullScan_12", - " └─TableFullScan_12 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 8000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─HashJoin 8000.00 root Null-aware anti semi join, equal:[eq(test.t1.a, test.t2.b)]", + " ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + " │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:b(b) keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_10 7992.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─HashJoin_29 7992.00 root semi join, equal:[eq(test.t1.a, test.t2.b)], other cond:gt(test.t2.c, test.t1.c)", - " ├─TableReader_43(Build) 9980.01 root data:Selection_42", - " │ └─Selection_42 9980.01 cop[tikv] not(isnull(test.t2.b)), not(isnull(test.t2.c))", - " │ └─TableFullScan_41 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─TableReader_40(Probe) 9990.00 root data:Selection_39", - " └─Selection_39 9990.00 cop[tikv] not(isnull(test.t1.c))", - " └─TableFullScan_38 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 7992.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─HashJoin 7992.00 root semi join, equal:[eq(test.t1.a, test.t2.b)], other cond:gt(test.t2.c, test.t1.c)", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.b)), not(isnull(test.t2.c))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t1.c))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_10 8000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─HashJoin_12 8000.00 root Null-aware anti semi join, equal:[eq(test.t1.a, test.t2.b)], other cond:gt(test.t2.c, test.t1.c)", - " ├─TableReader_16(Build) 10000.00 root data:TableFullScan_15", - " │ └─TableFullScan_15 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─TableReader_14(Probe) 10000.00 root data:TableFullScan_13", - " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 8000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─HashJoin 8000.00 root Null-aware anti semi join, equal:[eq(test.t1.a, test.t2.b)], other cond:gt(test.t2.c, test.t1.c)", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_10 7992.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─HashJoin_12 7992.00 root CARTESIAN semi join, other cond:gt(test.t2.c, test.t1.c)", - " ├─TableReader_18(Build) 9990.00 root data:Selection_17", - " │ └─Selection_17 9990.00 cop[tikv] not(isnull(test.t2.c))", - " │ └─TableFullScan_16 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─TableReader_15(Probe) 9990.00 root data:Selection_14", - " └─Selection_14 9990.00 cop[tikv] not(isnull(test.t1.c))", - " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 7992.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─HashJoin 7992.00 root CARTESIAN semi join, other cond:gt(test.t2.c, test.t1.c)", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.c))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t1.c))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_10 8000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─HashJoin_12 8000.00 root CARTESIAN anti semi join, other cond:gt(test.t2.c, test.t1.c)", - " ├─TableReader_16(Build) 10000.00 root data:TableFullScan_15", - " │ └─TableFullScan_15 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─TableReader_14(Probe) 10000.00 root data:TableFullScan_13", - " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 8000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─HashJoin 8000.00 root CARTESIAN anti semi join, other cond:gt(test.t2.c, test.t1.c)", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_10 7992.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─HashJoin_12 7992.00 root semi join, equal:[eq(test.t1.c, test.t2.c)]", - " ├─TableReader_18(Build) 9990.00 root data:Selection_17", - " │ └─Selection_17 9990.00 cop[tikv] not(isnull(test.t2.c))", - " │ └─TableFullScan_16 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─TableReader_15(Probe) 9990.00 root data:Selection_14", - " └─Selection_14 9990.00 cop[tikv] not(isnull(test.t1.c))", - " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 7992.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─HashJoin 7992.00 root semi join, equal:[eq(test.t1.c, test.t2.c)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.c))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t1.c))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_10 8000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─HashJoin_12 8000.00 root anti semi join, equal:[eq(test.t1.c, test.t2.c)]", - " ├─TableReader_16(Build) 10000.00 root data:TableFullScan_15", - " │ └─TableFullScan_15 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─TableReader_14(Probe) 10000.00 root data:TableFullScan_13", - " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 8000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─HashJoin 8000.00 root anti semi join, equal:[eq(test.t1.c, test.t2.c)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Projection_9 12487.50 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─Sort_10 12487.50 root test.t1.a, test.t1.b, test.t1.c, test.t1.d, test.t2.b", - " └─HashJoin_37 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", - " ├─IndexReader_51(Build) 9990.00 root index:IndexFullScan_50", - " │ └─IndexFullScan_50 9990.00 cop[tikv] table:t2, index:b(b) keep order:false, stats:pseudo", - " └─TableReader_46(Probe) 9990.00 root data:Selection_45", - " └─Selection_45 9990.00 cop[tikv] not(isnull(test.t1.b))", - " └─TableFullScan_44 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Projection 12487.50 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─Sort 12487.50 root test.t1.a, test.t1.b, test.t1.c, test.t1.d, test.t2.b", + " └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", + " ├─IndexReader(Build) 9990.00 root index:IndexFullScan", + " │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:b(b) keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] } ] @@ -287,45 +287,45 @@ "Cases": [ { "Plan": [ - "Sort_9 12500.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d, test.t2.a, test.t2.b, test.t2.c, test.t2.d", - "└─MergeJoin_11 12500.00 root inner join, left key:test.t1.a, right key:test.t2.a", - " ├─TableReader_35(Build) 10000.00 root data:TableFullScan_34", - " │ └─TableFullScan_34 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", - " └─TableReader_33(Probe) 10000.00 root data:TableFullScan_32", - " └─TableFullScan_32 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" + "Sort 12500.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d, test.t2.a, test.t2.b, test.t2.c, test.t2.d", + "└─MergeJoin 12500.00 root inner join, left key:test.t1.a, right key:test.t2.a", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" ] }, { "Plan": [ - "Sort_9 12475.01 root test.t1.a, test.t1.b, test.t1.c, test.t1.d, test.t2.a, test.t2.b, test.t2.c, test.t2.d", - "└─HashJoin_42 12475.01 root inner join, equal:[eq(test.t1.b, test.t2.b)], other cond:gt(test.t1.a, test.t2.a), lt(test.t1.c, test.t2.c)", - " ├─TableReader_61(Build) 9980.01 root data:Selection_60", - " │ └─Selection_60 9980.01 cop[tikv] not(isnull(test.t2.b)), not(isnull(test.t2.c))", - " │ └─TableFullScan_59 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─TableReader_54(Probe) 9980.01 root data:Selection_53", - " └─Selection_53 9980.01 cop[tikv] not(isnull(test.t1.b)), not(isnull(test.t1.c))", - " └─TableFullScan_52 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 12475.01 root test.t1.a, test.t1.b, test.t1.c, test.t1.d, test.t2.a, test.t2.b, test.t2.c, test.t2.d", + "└─HashJoin 12475.01 root inner join, equal:[eq(test.t1.b, test.t2.b)], other cond:gt(test.t1.a, test.t2.a), lt(test.t1.c, test.t2.c)", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.b)), not(isnull(test.t2.c))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9980.01 root data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t1.b)), not(isnull(test.t1.c))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_8 12500.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─MergeJoin_10 12500.00 root left outer join, left key:test.t1.a, right key:test.t2.a", - " ├─TableReader_25(Build) 10000.00 root data:TableFullScan_24", - " │ └─TableFullScan_24 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", - " └─TableReader_23(Probe) 10000.00 root data:TableFullScan_22", - " └─TableFullScan_22 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" + "Sort 12500.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─MergeJoin 12500.00 root left outer join, left key:test.t1.a, right key:test.t2.a", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" ] }, { "Plan": [ - "Projection_8 100000000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─Sort_9 100000000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d, test.t2.a", - " └─HashJoin_11 100000000.00 root CARTESIAN inner join, other cond:ne(test.t1.a, test.t2.a)", - " ├─IndexReader_18(Build) 10000.00 root index:IndexFullScan_17", - " │ └─IndexFullScan_17 10000.00 cop[tikv] table:t2, index:b(b) keep order:false, stats:pseudo", - " └─TableReader_14(Probe) 10000.00 root data:TableFullScan_13", - " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Projection 100000000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─Sort 100000000.00 root test.t1.a, test.t1.b, test.t1.c, test.t1.d, test.t2.a", + " └─HashJoin 100000000.00 root CARTESIAN inner join, other cond:ne(test.t1.a, test.t2.a)", + " ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + " │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:b(b) keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] } ] @@ -335,102 +335,102 @@ "Cases": [ { "Plan": [ - "Batch_Point_Get_9 3.00 root table:t1 handle:[1 222 33333], keep order:true, desc:false" + "Batch_Point_Get 3.00 root table:t1 handle:[1 222 33333], keep order:true, desc:false" ] }, { "Plan": [ - "Batch_Point_Get_9 4.00 root table:t1 handle:[1 2 3 4], keep order:true, desc:false" + "Batch_Point_Get 4.00 root table:t1 handle:[1 2 3 4], keep order:true, desc:false" ] }, { "Plan": [ - "Batch_Point_Get_9 3.00 root table:t1, index:b(b) keep order:true, desc:false" + "Batch_Point_Get 3.00 root table:t1, index:b(b) keep order:true, desc:false" ] }, { "Plan": [ - "Batch_Point_Get_9 4.00 root table:t1, index:b(b) keep order:true, desc:false" + "Batch_Point_Get 4.00 root table:t1, index:b(b) keep order:true, desc:false" ] }, { "Plan": [ - "Sort_11 6666.67 root Column#9, Column#10, Column#11, Column#12", - "└─Union_13 6666.67 root ", - " ├─TableReader_16 3333.33 root data:TableRangeScan_15", - " │ └─TableRangeScan_15 3333.33 cop[tikv] table:t1 range:(10,+inf], keep order:false, stats:pseudo", - " └─TableReader_20 3333.33 root data:Selection_19", - " └─Selection_19 3333.33 cop[tikv] gt(test.t2.b, 20)", - " └─TableFullScan_18 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + "Sort 6666.67 root Column#9, Column#10, Column#11, Column#12", + "└─Union 6666.67 root ", + " ├─TableReader 3333.33 root data:TableRangeScan", + " │ └─TableRangeScan 3333.33 cop[tikv] table:t1 range:(10,+inf], keep order:false, stats:pseudo", + " └─TableReader 3333.33 root data:Selection", + " └─Selection 3333.33 cop[tikv] gt(test.t2.b, 20)", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_12 5333.33 root Column#9, Column#10, Column#11, Column#12", - "└─HashAgg_14 5333.33 root group by:Column#10, Column#11, Column#12, Column#9, funcs:firstrow(Column#9)->Column#9, funcs:firstrow(Column#10)->Column#10, funcs:firstrow(Column#11)->Column#11, funcs:firstrow(Column#12)->Column#12", - " └─Union_15 6666.67 root ", - " ├─TableReader_18 3333.33 root data:TableRangeScan_17", - " │ └─TableRangeScan_17 3333.33 cop[tikv] table:t1 range:(10,+inf], keep order:false, stats:pseudo", - " └─TableReader_22 3333.33 root data:Selection_21", - " └─Selection_21 3333.33 cop[tikv] gt(test.t2.b, 20)", - " └─TableFullScan_20 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + "Sort 5333.33 root Column#9, Column#10, Column#11, Column#12", + "└─HashAgg 5333.33 root group by:Column#10, Column#11, Column#12, Column#9, funcs:firstrow(Column#9)->Column#9, funcs:firstrow(Column#10)->Column#10, funcs:firstrow(Column#11)->Column#11, funcs:firstrow(Column#12)->Column#12", + " └─Union 6666.67 root ", + " ├─TableReader 3333.33 root data:TableRangeScan", + " │ └─TableRangeScan 3333.33 cop[tikv] table:t1 range:(10,+inf], keep order:false, stats:pseudo", + " └─TableReader 3333.33 root data:Selection", + " └─Selection 3333.33 cop[tikv] gt(test.t2.b, 20)", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_11 2666.67 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─HashJoin_13 2666.67 root CARTESIAN semi join, other cond:nulleq(test.t1.a, test.t2.a), nulleq(test.t1.b, test.t2.b), nulleq(test.t1.c, test.t2.c), nulleq(test.t1.d, test.t2.d)", - " ├─TableReader_20(Build) 3333.33 root data:Selection_19", - " │ └─Selection_19 3333.33 cop[tikv] gt(test.t2.b, 20)", - " │ └─TableFullScan_18 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─TableReader_16(Probe) 3333.33 root data:TableRangeScan_15", - " └─TableRangeScan_15 3333.33 cop[tikv] table:t1 range:(10,+inf], keep order:false, stats:pseudo" + "Sort 2666.67 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─HashJoin 2666.67 root CARTESIAN semi join, other cond:nulleq(test.t1.a, test.t2.a), nulleq(test.t1.b, test.t2.b), nulleq(test.t1.c, test.t2.c), nulleq(test.t1.d, test.t2.d)", + " ├─TableReader(Build) 3333.33 root data:Selection", + " │ └─Selection 3333.33 cop[tikv] gt(test.t2.b, 20)", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 3333.33 root data:TableRangeScan", + " └─TableRangeScan 3333.33 cop[tikv] table:t1 range:(10,+inf], keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_11 2666.67 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", - "└─HashJoin_13 2666.67 root anti semi join, equal:[nulleq(test.t1.a, test.t2.a) nulleq(test.t1.b, test.t2.b) nulleq(test.t1.c, test.t2.c) nulleq(test.t1.d, test.t2.d)]", - " ├─TableReader_20(Build) 3333.33 root data:Selection_19", - " │ └─Selection_19 3333.33 cop[tikv] gt(test.t2.b, 20)", - " │ └─TableFullScan_18 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - " └─TableReader_16(Probe) 3333.33 root data:TableRangeScan_15", - " └─TableRangeScan_15 3333.33 cop[tikv] table:t1 range:(10,+inf], keep order:false, stats:pseudo" + "Sort 2666.67 root test.t1.a, test.t1.b, test.t1.c, test.t1.d", + "└─HashJoin 2666.67 root anti semi join, equal:[nulleq(test.t1.a, test.t2.a) nulleq(test.t1.b, test.t2.b) nulleq(test.t1.c, test.t2.c) nulleq(test.t1.d, test.t2.d)]", + " ├─TableReader(Build) 3333.33 root data:Selection", + " │ └─Selection 3333.33 cop[tikv] gt(test.t2.b, 20)", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─TableReader(Probe) 3333.33 root data:TableRangeScan", + " └─TableRangeScan 3333.33 cop[tikv] table:t1 range:(10,+inf], keep order:false, stats:pseudo" ] }, { "Plan": [ - "Projection_8 10000.00 root Column#6->Column#7", - "└─Sort_9 10000.00 root test.t1.b, test.t1.a, Column#6", - " └─Window_11 10000.00 root sum(cast(test.t1.b, decimal(10,0) BINARY))->Column#6 over(partition by test.t1.a)", - " └─TableReader_13 10000.00 root data:TableFullScan_12", - " └─TableFullScan_12 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" + "Projection 10000.00 root Column#6->Column#7", + "└─Sort 10000.00 root test.t1.b, test.t1.a, Column#6", + " └─Window 10000.00 root sum(cast(test.t1.b, decimal(10,0) BINARY))->Column#6 over(partition by test.t1.a)", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" ] }, { "Plan": [ - "Sort_6 8000.00 root Column#5, Column#6, Column#7", - "└─HashAgg_12 8000.00 root group by:test.t1.d, funcs:min(Column#8)->Column#5, funcs:max(Column#9)->Column#6, funcs:sum(Column#10)->Column#7", - " └─TableReader_13 8000.00 root data:HashAgg_8", - " └─HashAgg_8 8000.00 cop[tikv] group by:test.t1.d, funcs:min(test.t1.a)->Column#8, funcs:max(test.t1.b)->Column#9, funcs:sum(test.t1.c)->Column#10", - " └─TableFullScan_11 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 8000.00 root Column#5, Column#6, Column#7", + "└─HashAgg 8000.00 root group by:test.t1.d, funcs:min(Column#8)->Column#5, funcs:max(Column#9)->Column#6, funcs:sum(Column#10)->Column#7", + " └─TableReader 8000.00 root data:HashAgg", + " └─HashAgg 8000.00 cop[tikv] group by:test.t1.d, funcs:min(test.t1.a)->Column#8, funcs:max(test.t1.b)->Column#9, funcs:sum(test.t1.c)->Column#10", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Sort_9 6400.00 root Column#5, Column#6, Column#7", - "└─Selection_11 6400.00 root lt(Column#6, 20)", - " └─HashAgg_16 8000.00 root group by:test.t1.d, funcs:min(Column#11)->Column#5, funcs:max(Column#12)->Column#6, funcs:sum(Column#13)->Column#7", - " └─TableReader_17 8000.00 root data:HashAgg_12", - " └─HashAgg_12 8000.00 cop[tikv] group by:test.t1.d, funcs:min(test.t1.a)->Column#11, funcs:max(test.t1.b)->Column#12, funcs:sum(test.t1.c)->Column#13", - " └─TableFullScan_15 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + "Sort 6400.00 root Column#5, Column#6, Column#7", + "└─Selection 6400.00 root lt(Column#6, 20)", + " └─HashAgg 8000.00 root group by:test.t1.d, funcs:min(Column#11)->Column#5, funcs:max(Column#12)->Column#6, funcs:sum(Column#13)->Column#7", + " └─TableReader 8000.00 root data:HashAgg", + " └─HashAgg 8000.00 cop[tikv] group by:test.t1.d, funcs:min(test.t1.a)->Column#11, funcs:max(test.t1.b)->Column#12, funcs:sum(test.t1.c)->Column#13", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" ] }, { "Plan": [ - "Projection_4 10000.00 root case(eq(test.t1.a, 1), a1, eq(test.t1.a, 2), a2, ax)->Column#5", - "└─TableReader_12 10000.00 root data:TableFullScan_11", - " └─TableFullScan_11 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" + "Projection 10000.00 root case(eq(test.t1.a, 1), a1, eq(test.t1.a, 2), a2, ax)->Column#5", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" ] } ] @@ -440,25 +440,26 @@ "Cases": [ { "Plan": [ - "Batch_Point_Get_9 2.00 root table:thash handle:[1 200], keep order:true, desc:false" + "TableReader 2.00 root partition:p0,p1 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:thash range:[1,1], [200,200], keep order:true, stats:pseudo" ] }, { "Plan": [ - "TableReader_11 100.00 root partition:all data:TableRangeScan_10", - "└─TableRangeScan_10 100.00 cop[tikv] table:thash range:[50,150], keep order:true, stats:pseudo" + "TableReader 100.00 root partition:all data:TableRangeScan", + "└─TableRangeScan 100.00 cop[tikv] table:thash range:[50,150], keep order:true, stats:pseudo" ] }, { "Plan": [ - "TableReader_11 2.00 root partition:p0,p2 data:TableRangeScan_10", - "└─TableRangeScan_10 2.00 cop[tikv] table:trange range:[1,1], [200,200], keep order:true, stats:pseudo" + "TableReader 2.00 root partition:p0,p2 data:TableRangeScan", + "└─TableRangeScan 2.00 cop[tikv] table:trange range:[1,1], [200,200], keep order:true, stats:pseudo" ] }, { "Plan": [ - "TableReader_11 100.00 root partition:p0,p1 data:TableRangeScan_10", - "└─TableRangeScan_10 100.00 cop[tikv] table:trange range:[50,150], keep order:true, stats:pseudo" + "TableReader 100.00 root partition:p0,p1 data:TableRangeScan", + "└─TableRangeScan 100.00 cop[tikv] table:trange range:[50,150], keep order:true, stats:pseudo" ] } ] diff --git a/planner/core/find_best_task.go b/planner/core/find_best_task.go index d2e6730b8cccf..a7a44eb3961ae 100644 --- a/planner/core/find_best_task.go +++ b/planner/core/find_best_task.go @@ -1116,15 +1116,12 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter } } } - var hashPartColName *model.CIStr + var partColName *model.CIStr if tblInfo := ds.table.Meta(); canConvertPointGet && tblInfo.GetPartitionInfo() != nil { if canConvertPointGet && len(path.Ranges) > 1 { - // We can only build batch point get for hash partitions on a simple column now. This is - // decided by the current implementation of `BatchPointGetExec::initialize()`, specifically, - // the `getPhysID()` function. Once we optimize that part, we can come back and enable - // BatchPointGet plan for more cases. - hashPartColName = getHashOrKeyPartitionColumnName(ds.SCtx(), tblInfo) - if hashPartColName == nil { + // not support some complex situation, like `by HASH( col DIV 80 )` etc. + partColName = getPartitionColumnName(getPartitionExpr(ds.SCtx(), tblInfo), tblInfo) + if partColName == nil { canConvertPointGet = false } } @@ -1153,7 +1150,7 @@ func (ds *DataSource) findBestTask(prop *property.PhysicalProperty, planCounter if len(path.Ranges) == 1 { pointGetTask = ds.convertToPointGet(prop, candidate) } else { - pointGetTask = ds.convertToBatchPointGet(prop, candidate, hashPartColName) + pointGetTask = ds.convertToBatchPointGet(prop, candidate, partColName) } // Batch/PointGet plans may be over-optimized, like `a>=1(?) and a<=1(?)` --> `a=1` --> PointGet(a=1). @@ -2430,7 +2427,7 @@ func (ds *DataSource) convertToPointGet(prop *property.PhysicalProperty, candida return rTsk } -func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, candidate *candidatePath, hashPartColName *model.CIStr) (task task) { +func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, candidate *candidatePath, partColName *model.CIStr) (task task) { if !prop.IsSortItemEmpty() && !candidate.isMatchProp { return invalidTask } @@ -2452,6 +2449,10 @@ func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, ca PartitionExpr: getPartitionExpr(ds.SCtx(), ds.TableInfo()), } if batchPointGetPlan.KeepOrder { + // TODO: support keepOrder for partition table with dynamic pruning + if ds.TableInfo().GetPartitionInfo() != nil && ds.SCtx().GetSessionVars().StmtCtx.UseDynamicPruneMode { + return invalidTask + } batchPointGetPlan.Desc = prop.SortItems[0].Desc } rTsk := &rootTask{} @@ -2473,7 +2474,7 @@ func (ds *DataSource) convertToBatchPointGet(prop *property.PhysicalProperty, ca batchPointGetPlan.IndexInfo = candidate.path.Index batchPointGetPlan.IdxCols = candidate.path.IdxCols batchPointGetPlan.IdxColLens = candidate.path.IdxColLens - batchPointGetPlan.PartitionColPos = getColumnPosInIndex(candidate.path.Index, hashPartColName) + batchPointGetPlan.PartitionColPos = getColumnPosInIndex(candidate.path.Index, partColName) for _, ran := range candidate.path.Ranges { batchPointGetPlan.IndexValues = append(batchPointGetPlan.IndexValues, ran.LowVal) } diff --git a/planner/core/point_get_plan.go b/planner/core/point_get_plan.go index bf6190575858f..e0758f53460ef 100644 --- a/planner/core/point_get_plan.go +++ b/planner/core/point_get_plan.go @@ -1892,17 +1892,31 @@ func getPartitionColumnPos(idx *model.IndexInfo, partitionExpr *tables.Partition return 0, nil } + partitionColName := getPartitionColumnName(partitionExpr, tbl) + if partitionColName == nil { + return 0, errors.Errorf("unsupported partition type in BatchGet") + } + + return getColumnPosInIndex(idx, partitionColName), nil +} + +func getPartitionColumnName(partitionExpr *tables.PartitionExpr, tbl *model.TableInfo) *model.CIStr { + if partitionExpr == nil { + return nil + } + + pi := tbl.GetPartitionInfo() var partitionColName model.CIStr switch pi.Type { case model.PartitionTypeHash: col, ok := partitionExpr.OrigExpr.(*ast.ColumnNameExpr) if !ok { - return 0, errors.Errorf("unsupported partition type in BatchGet") + return nil } partitionColName = col.Name.Name case model.PartitionTypeKey: if len(partitionExpr.KeyPartCols) != 1 { - return 0, errors.Errorf("unsupported partition type in BatchGet") + return nil } colInfo := findColNameByColID(tbl.Columns, partitionExpr.KeyPartCols[0]) partitionColName = colInfo.Name @@ -1910,7 +1924,7 @@ func getPartitionColumnPos(idx *model.IndexInfo, partitionExpr *tables.Partition // left range columns partition for future development col, ok := partitionExpr.Expr.(*expression.Column) if !(ok && len(pi.Columns) == 0) { - return 0, errors.Errorf("unsupported partition type in BatchGet") + return nil } colInfo := findColNameByColID(tbl.Columns, col) partitionColName = colInfo.Name @@ -1918,13 +1932,13 @@ func getPartitionColumnPos(idx *model.IndexInfo, partitionExpr *tables.Partition // left list columns partition for future development locateExpr, ok := partitionExpr.ForListPruning.LocateExpr.(*expression.Column) if !(ok && partitionExpr.ForListPruning.ColPrunes == nil) { - return 0, errors.Errorf("unsupported partition type in BatchGet") + return nil } colInfo := findColNameByColID(tbl.Columns, locateExpr) partitionColName = colInfo.Name } - return getColumnPosInIndex(idx, &partitionColName), nil + return &partitionColName } // getColumnPosInIndex gets the column's position in the index. @@ -1957,36 +1971,6 @@ func getPartitionExpr(ctx sessionctx.Context, tbl *model.TableInfo) *tables.Part return partTable.PartitionExpr() } -func getHashOrKeyPartitionColumnName(ctx sessionctx.Context, tbl *model.TableInfo) *model.CIStr { - pi := tbl.GetPartitionInfo() - if pi == nil { - return nil - } - if pi.Type != model.PartitionTypeHash && pi.Type != model.PartitionTypeKey { - return nil - } - is := ctx.GetInfoSchema().(infoschema.InfoSchema) - table, ok := is.TableByID(tbl.ID) - if !ok { - return nil - } - // PartitionExpr don't need columns and names for hash partition. - partitionExpr := table.(partitionTable).PartitionExpr() - if pi.Type == model.PartitionTypeKey { - // used to judge whether the key partition contains only one field - if len(pi.Columns) != 1 { - return nil - } - return &pi.Columns[0] - } - expr := partitionExpr.OrigExpr - col, ok := expr.(*ast.ColumnNameExpr) - if !ok { - return nil - } - return &col.Name.Name -} - func findColNameByColID(cols []*model.ColumnInfo, col *expression.Column) *model.ColumnInfo { for _, c := range cols { if c.ID == col.ID { diff --git a/planner/core/point_get_plan_test.go b/planner/core/point_get_plan_test.go index f4fbafac4edc8..e1093ecb64cc4 100644 --- a/planner/core/point_get_plan_test.go +++ b/planner/core/point_get_plan_test.go @@ -21,7 +21,6 @@ import ( "testing" "time" - "github.com/pingcap/failpoint" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/planner" @@ -623,67 +622,6 @@ func TestBatchPointGetPartition(t *testing.T) { tk.MustQuery("select * from t where (a, b) in ((1, 1), (2, 2), (3, 3), (4, 4))").Check(testkit.Rows()) } -func TestBatchPointGetPartitionForAccessObject(t *testing.T) { - failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`) - defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune") - store := testkit.CreateMockStore(t) - - tk := testkit.NewTestKit(t, store) - tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'") - tk.MustExec("use test") - tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b int, UNIQUE KEY (b)) PARTITION BY HASH(b) PARTITIONS 4") - tk.MustExec("insert into t values(1, 1), (2, 2), (3, 3), (4, 4)") - tk.MustQuery("explain select * from t where b in (1, 2)").Check(testkit.Rows( - "Batch_Point_Get_1 2.00 root table:t, partition:p1,p2, index:b(b) keep order:false, desc:false")) - tk.MustQuery("explain select * from t where b in (1, 2, 1)").Check(testkit.Rows( - "Batch_Point_Get_1 3.00 root table:t, partition:p1,p2, index:b(b) keep order:false, desc:false")) - - tk.MustExec("set @@session.tidb_enable_list_partition = ON") - tk.MustExec("drop table if exists t") - tk.MustExec("CREATE TABLE t (id int primary key, name_id int) PARTITION BY LIST(id) (" + - "partition p0 values IN (1, 2), " + - "partition p1 values IN (3, 4), " + - "partition p3 values IN (5))") - tk.MustExec("insert into t values(1, 1), (2, 2), (3, 3), (4, 4)") - tk.MustQuery("explain format='brief' select * from t where id in (1, 3)").Check(testkit.Rows( - "Batch_Point_Get 2.00 root table:t, partition:p0,p1 handle:[1 3], keep order:false, desc:false")) - - tk.MustExec("set @@session.tidb_enable_list_partition = ON") - tk.MustExec("drop table if exists t0") - tk.MustExec("CREATE TABLE t0 (id int primary key, name_id int) PARTITION BY LIST COLUMNS(id) (" + - "partition p0 values IN (1, 2), " + - "partition p1 values IN (3, 4), " + - "partition p3 values IN (5))") - tk.MustExec("insert into t0 values(1, 1), (2, 2), (3, 3), (4, 4)") - tk.MustQuery("explain format='brief' select * from t0 where id in (1, 3)").Check(testkit.Rows( - "TableReader 2.00 root partition:p0,p1 data:TableRangeScan]\n" + - "[└─TableRangeScan 2.00 cop[tikv] table:t0 range:[1,1], [3,3], keep order:false, stats:pseudo")) - - tk.MustExec("set @@session.tidb_enable_list_partition = ON") - tk.MustExec("drop table if exists t1") - tk.MustExec("CREATE TABLE t1 (id int, name_id int, unique key(id, name_id)) PARTITION BY LIST COLUMNS(id, name_id) (" + - "partition p0 values IN ((1, 1),(2, 2)), " + - "partition p1 values IN ((3, 3),(4, 4)), " + - "partition p3 values IN ((5, 5)))") - tk.MustExec("insert into t1 values(1, 1), (2, 2), (3, 3), (4, 4)") - tk.MustQuery("explain format='brief' select * from t1 where (id, name_id) in ((1, 1), (3, 3))").Check(testkit.Rows( - "IndexReader 2.00 root partition:p0,p1 index:IndexRangeScan]\n" + - "[└─IndexRangeScan 2.00 cop[tikv] table:t1, index:id(id, name_id) range:[1 1,1 1], [3 3,3 3], keep order:false, stats:pseudo")) - - tk.MustExec("set @@session.tidb_enable_list_partition = ON") - tk.MustExec("drop table if exists t2") - tk.MustExec("CREATE TABLE t2 (id int, name varchar(10), unique key(id, name)) PARTITION BY LIST COLUMNS(id, name) (" + - "partition p0 values IN ((1,'a'),(2,'b')), " + - "partition p1 values IN ((3,'c'),(4,'d')), " + - "partition p3 values IN ((5,'e')))") - tk.MustExec("insert into t2 values(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')") - tk.MustQuery("explain format='brief' select * from t2 where (id, name) in ((1, 'a'), (3, 'c'))").Check(testkit.Rows( - "IndexReader 2.00 root partition:p0,p1 index:IndexRangeScan]\n" + - "[└─IndexRangeScan 2.00 cop[tikv] table:t2, index:id(id, name) range:[1 \"a\",1 \"a\"], [3 \"c\",3 \"c\"], keep order:false, stats:pseudo")) -} - func TestIssue19141(t *testing.T) { // For issue 19141, fix partition selection on batch point get. store := testkit.CreateMockStore(t)