diff --git a/cmd/explaintest/r/explain_easy_stats.result b/cmd/explaintest/r/explain_easy_stats.result index d4bf4c9026156..b0f5e6b277859 100644 --- a/cmd/explaintest/r/explain_easy_stats.result +++ b/cmd/explaintest/r/explain_easy_stats.result @@ -179,7 +179,9 @@ id estRows task access object operator info Point_Get 1.00 root table:index_prune, index:PRIMARY(a, b) explain format = 'brief' select * from index_prune WHERE a = 1010010404050976781 AND b = 26467085526790 GROUP BY b ORDER BY a limit 1; id estRows task access object operator info -Point_Get 1.00 root table:index_prune, index:PRIMARY(a, b) +TopN 1.00 root test.index_prune.a, offset:0, count:1 +└─StreamAgg 1.00 root group by:test.index_prune.b, funcs:firstrow(test.index_prune.a)->test.index_prune.a, funcs:firstrow(test.index_prune.b)->test.index_prune.b, funcs:firstrow(test.index_prune.c)->test.index_prune.c + └─Point_Get 1.00 root table:index_prune, index:PRIMARY(a, b) drop table if exists t1, t2, t3, index_prune; set @@session.tidb_opt_insubq_to_join_and_agg=1; drop table if exists tbl; diff --git a/executor/executor_test.go b/executor/executor_test.go index 10b4f30b3ef96..dbeb299d5d3d6 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -5045,6 +5045,82 @@ func TestIsPointGet(t *testing.T) { } } +func TestCheckActRowsWithUnistore(t *testing.T) { + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.EnableCollectExecutionInfo = true + }) + store := testkit.CreateMockStore(t) + // testSuite1 use default mockstore which is unistore + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_cost_model_version=2") + tk.MustExec("drop table if exists t_unistore_act_rows") + tk.MustExec("create table t_unistore_act_rows(a int, b int, index(a, b))") + tk.MustExec("insert into t_unistore_act_rows values (1, 0), (1, 0), (2, 0), (2, 1)") + tk.MustExec("analyze table t_unistore_act_rows") + tk.MustExec("set @@tidb_merge_join_concurrency= 5;") + + type testStruct struct { + sql string + expected []string + } + + tests := []testStruct{ + { + sql: "select * from t_unistore_act_rows", + expected: []string{"4", "4"}, + }, + { + sql: "select * from t_unistore_act_rows where a > 1", + expected: []string{"2", "2"}, + }, + { + sql: "select * from t_unistore_act_rows where a > 1 and b > 0", + expected: []string{"1", "1", "2"}, + }, + { + sql: "select b from t_unistore_act_rows", + expected: []string{"4", "4"}, + }, + { + sql: "select * from t_unistore_act_rows where b > 0", + expected: []string{"1", "1", "4"}, + }, + { + sql: "select count(*) from t_unistore_act_rows", + expected: []string{"1", "1", "1", "4"}, + }, + { + sql: "select count(*) from t_unistore_act_rows group by a", + expected: []string{"2", "2", "2", "4"}, + }, + { + sql: "select count(*) from t_unistore_act_rows group by b", + expected: []string{"2", "4", "4"}, + }, + { + sql: "with cte(a) as (select a from t_unistore_act_rows) select (select 1 from cte limit 1) from cte;", + expected: []string{"4", "1", "1", "1", "4", "4", "4", "4", "4"}, + }, + { + sql: "select a, row_number() over (partition by b) from t_unistore_act_rows;", + expected: []string{"4", "4", "4", "4", "4", "4", "4"}, + }, + { + sql: "select /*+ merge_join(t1, t2) */ * from t_unistore_act_rows t1 join t_unistore_act_rows t2 on t1.b = t2.b;", + expected: []string{"10", "10", "4", "4", "4", "4", "4", "4", "4", "4", "4", "4"}, + }, + } + + // Default RPC encoding may cause statistics explain result differ and then the test unstable. + tk.MustExec("set @@tidb_enable_chunk_rpc = on") + + for _, test := range tests { + checkActRows(t, tk, test.sql, test.expected) + } +} + func TestClusteredIndexIsPointGet(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) diff --git a/executor/explain_test.go b/executor/explain_test.go index 8495bc73bad0d..f93f5faab05b5 100644 --- a/executor/explain_test.go +++ b/executor/explain_test.go @@ -24,7 +24,6 @@ import ( "testing" "time" - "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/parser/auth" plannercore "github.com/pingcap/tidb/planner/core" @@ -315,80 +314,12 @@ func checkActRows(t *testing.T, tk *testkit.TestKit, sql string, expected []stri } } -func TestCheckActRowsWithUnistore(t *testing.T) { - defer config.RestoreFunc()() - config.UpdateGlobal(func(conf *config.Config) { - conf.EnableCollectExecutionInfo = true - }) +func TestPointGetOrderby(t *testing.T) { store := testkit.CreateMockStore(t) - // testSuite1 use default mockstore which is unistore tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("set tidb_cost_model_version=2") - tk.MustExec("drop table if exists t_unistore_act_rows") - tk.MustExec("create table t_unistore_act_rows(a int, b int, index(a, b))") - tk.MustExec("insert into t_unistore_act_rows values (1, 0), (1, 0), (2, 0), (2, 1)") - tk.MustExec("analyze table t_unistore_act_rows") - tk.MustExec("set @@tidb_merge_join_concurrency= 5;") - - type testStruct struct { - sql string - expected []string - } - - tests := []testStruct{ - { - sql: "select * from t_unistore_act_rows", - expected: []string{"4", "4"}, - }, - { - sql: "select * from t_unistore_act_rows where a > 1", - expected: []string{"2", "2"}, - }, - { - sql: "select * from t_unistore_act_rows where a > 1 and b > 0", - expected: []string{"1", "1", "2"}, - }, - { - sql: "select b from t_unistore_act_rows", - expected: []string{"4", "4"}, - }, - { - sql: "select * from t_unistore_act_rows where b > 0", - expected: []string{"1", "1", "4"}, - }, - { - sql: "select count(*) from t_unistore_act_rows", - expected: []string{"1", "1", "1", "4"}, - }, - { - sql: "select count(*) from t_unistore_act_rows group by a", - expected: []string{"2", "2", "2", "4"}, - }, - { - sql: "select count(*) from t_unistore_act_rows group by b", - expected: []string{"2", "4", "4"}, - }, - { - sql: "with cte(a) as (select a from t_unistore_act_rows) select (select 1 from cte limit 1) from cte;", - expected: []string{"4", "1", "1", "1", "4", "4", "4", "4", "4"}, - }, - { - sql: "select a, row_number() over (partition by b) from t_unistore_act_rows;", - expected: []string{"4", "4", "4", "4", "4", "4", "4"}, - }, - { - sql: "select /*+ merge_join(t1, t2) */ * from t_unistore_act_rows t1 join t_unistore_act_rows t2 on t1.b = t2.b;", - expected: []string{"10", "10", "4", "4", "4", "4", "4", "4", "4", "4", "4", "4"}, - }, - } - - // Default RPC encoding may cause statistics explain result differ and then the test unstable. - tk.MustExec("set @@tidb_enable_chunk_rpc = on") - - for _, test := range tests { - checkActRows(t, tk, test.sql, test.expected) - } + tk.MustExec("create table t (i int key)") + require.Equal(t, tk.ExecToErr("select * from t where i = 1 order by j limit 10;").Error(), "[planner:1054]Unknown column 'j' in 'order clause'") } func TestExplainAnalyzeCTEMemoryAndDiskInfo(t *testing.T) { diff --git a/executor/historical_stats_test.go b/executor/historical_stats_test.go index 996ca85019ff5..6086f7b5c9d01 100644 --- a/executor/historical_stats_test.go +++ b/executor/historical_stats_test.go @@ -137,7 +137,7 @@ func TestRecordHistoryStatsMetaAfterAnalyze(t *testing.T) { tk.MustExec("delete from test.t where test.t.a = 1") err = h.DumpStatsDeltaToKV(handle.DumpAll) require.NoError(t, err) - tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = '%d' order by create_time desc", tableInfo.Meta().ID)).Sort().Check( + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = '%d'", tableInfo.Meta().ID)).Sort().Check( testkit.Rows("40 20")) tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta_history where table_id = '%d' order by create_time desc limit 1", tableInfo.Meta().ID)).Sort().Check( testkit.Rows("40 20")) @@ -146,7 +146,7 @@ func TestRecordHistoryStatsMetaAfterAnalyze(t *testing.T) { tk.MustExec("update test.t set test.t.b = 4 where test.t.a = 2") err = h.DumpStatsDeltaToKV(handle.DumpAll) require.NoError(t, err) - tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = '%d' order by create_time desc", tableInfo.Meta().ID)).Sort().Check( + tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta where table_id = '%d'", tableInfo.Meta().ID)).Sort().Check( testkit.Rows("50 20")) tk.MustQuery(fmt.Sprintf("select modify_count, count from mysql.stats_meta_history where table_id = '%d' order by create_time desc limit 1", tableInfo.Meta().ID)).Sort().Check( testkit.Rows("50 20")) diff --git a/planner/core/point_get_plan.go b/planner/core/point_get_plan.go index 1721d07d05d31..a56c20a545481 100644 --- a/planner/core/point_get_plan.go +++ b/planner/core/point_get_plan.go @@ -1015,7 +1015,7 @@ func tryWhereIn2BatchPointGet(ctx sessionctx.Context, selStmt *ast.SelectStmt) * // 3. All the columns must be public and not generated. // 4. The condition is an access path that the range is a unique key. func tryPointGetPlan(ctx sessionctx.Context, selStmt *ast.SelectStmt, check bool) *PointGetPlan { - if selStmt.Having != nil { + if selStmt.Having != nil || selStmt.OrderBy != nil { return nil } else if selStmt.Limit != nil { count, offset, err := extractLimitCountOffset(ctx, selStmt.Limit)