diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 7d97b4cfacbea..7d37dfcfe13f7 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -1330,9 +1330,13 @@ func TestKeepOrderHint(t *testing.T) { tk.MustExec("use test") tk.MustExec("set tidb_cost_model_version=2") - tk.MustExec("drop table if exists t, t1, t2") + tk.MustExec("drop table if exists t, t1, th") + tk.MustExec("drop view if exists v, v1") tk.MustExec("create table t(a int, b int, primary key(a));") - tk.MustExec("create table t1(a int, b int, index idx_a(a), index idx_b(b));") + tk.MustExec("create table t1(a int, b int, index idx_a(a));") + tk.MustExec("create table th (a int, key(a)) partition by hash(a) partitions 4;") + tk.MustExec("create definer='root'@'localhost' view v as select * from t1 where a<10 order by a limit 1;") + tk.MustExec("create definer='root'@'localhost' view v1 as select * from t where a<10 order by a limit 1;") // If the optimizer can not generate the keep order plan, it will report error err := tk.ExecToErr("explain select /*+ keep_order(t1, idx_a) */ * from t1 where a<10 limit 1;") @@ -1341,6 +1345,14 @@ func TestKeepOrderHint(t *testing.T) { err = tk.ExecToErr("explain select /*+ keep_order(t, primary) */ * from t where a<10 limit 1;") require.EqualError(t, err, "[planner:1815]Internal : Can't find a proper physical plan for this query") + // The partition table can not keep order + tk.MustExec("analyze table th;") + err = tk.ExecToErr("select a from th where a<1 order by a limit 1;") + require.NoError(t, err) + + err = tk.ExecToErr("select /*+ keep_order(th, a) */ a from th where a<1 order by a limit 1;") + require.EqualError(t, err, "[planner:1815]Internal : Can't find a proper physical plan for this query") + var input []string var output []struct { SQL string @@ -1361,6 +1373,46 @@ func TestKeepOrderHint(t *testing.T) { } } +func TestKeepOrderHintWithBinding(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("set tidb_cost_model_version=2") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(a int, b int, index idx_a(a));") + + // create binding for keep_order hint + tk.MustExec("select * from t1 where a<10 order by a limit 1;") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + tk.MustExec("create global binding for select * from t1 where a<10 order by a limit 1 using select /*+ keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1;") + tk.MustExec("select * from t1 where a<10 order by a limit 1;") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) + res := tk.MustQuery("show global bindings").Rows() + require.Equal(t, res[0][0], "select * from `test` . `t1` where `a` < ? order by `a` limit ?") + require.Equal(t, res[0][1], "SELECT /*+ keep_order(`t1` `idx_a`)*/ * FROM `test`.`t1` WHERE `a` < 10 ORDER BY `a` LIMIT 1") + + tk.MustExec("drop global binding for select * from t1 where a<10 order by a limit 1;") + tk.MustExec("select * from t1 where a<10 order by a limit 1;") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + res = tk.MustQuery("show global bindings").Rows() + require.Equal(t, len(res), 0) + + // create binding for no_keep_order hint + tk.MustExec("create global binding for select * from t1 where a<10 order by a limit 1 using select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1;") + tk.MustExec("select * from t1 where a<10 order by a limit 1;") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) + res = tk.MustQuery("show global bindings").Rows() + require.Equal(t, res[0][0], "select * from `test` . `t1` where `a` < ? order by `a` limit ?") + require.Equal(t, res[0][1], "SELECT /*+ no_keep_order(`t1` `idx_a`)*/ * FROM `test`.`t1` WHERE `a` < 10 ORDER BY `a` LIMIT 1") + + tk.MustExec("drop global binding for select * from t1 where a<10 order by a limit 1;") + tk.MustExec("select * from t1 where a<10 order by a limit 1;") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + res = tk.MustQuery("show global bindings").Rows() + require.Equal(t, len(res), 0) +} + func TestViewHint(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) diff --git a/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index 71123d8b85469..c5185349f0aa2 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -661,7 +661,50 @@ "explain select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", "explain select /*+ no_keep_order(t, primary) */ * from t where a<10 order by a limit 1;", "explain select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 limit 1;", - "explain select /*+ no_keep_order(t, primary) */ * from t where a<10 limit 1;" + "explain select /*+ no_keep_order(t, primary) */ * from t where a<10 limit 1;", + + // The index doesn't exist + "explain select /*+ keep_order(t1, idx_b) */ * from t1 where b<10 order by b limit 1;", + "explain select /*+ keep_order(t, idx_b) */ * from t where b<10 order by b limit 1;", + "explain select /*+ no_keep_order(t1, idx_b) */ * from t1 where b<10 order by b limit 1;", + "explain select /*+ no_keep_order(t, idx_b) */ * from t where b<10 order by b limit 1;", + + // Use the keep_order/ no_keep_order with the use_index/ ignore_index/ force_index hint at the same time + "explain select /*+ keep_order(t1, idx_a) use_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "explain select /*+ keep_order(t1, idx_a) */ * from t1 use index(idx_a) where a<10 order by a limit 1;", + "explain select /*+ keep_order(t1, idx_a) force_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "explain select /*+ keep_order(t1, idx_a) */ * from t1 force index(idx_a) where a<10 order by a limit 1;", + "explain select /*+ keep_order(t1, idx_a) ignore_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + + "explain select /*+ keep_order(t, primary) use_index(t, primary) */ * from t where a<10 order by a limit 1;", + "explain select /*+ keep_order(t, primary) */ * from t use index(primary) where a<10 order by a limit 1;", + "explain select /*+ keep_order(t, primary) force_index(t, primary) */ * from t where a<10 order by a limit 1;", + "explain select /*+ keep_order(t, primary) */ * from t force index(primary) where a<10 order by a limit 1;", + "explain select /*+ keep_order(t, primary) ignore_index(t, primary) */ * from t where a<10 order by a limit 1;", + + "explain select /*+ no_keep_order(t, primary) use_index(t, primary) */ * from t where a<10 order by a limit 1;", + "explain select /*+ no_keep_order(t, primary) */ * from t use index(primary) where a<10 order by a limit 1;", + "explain select /*+ no_keep_order(t, primary) force_index(t, primary) */ * from t where a<10 order by a limit 1;", + "explain select /*+ no_keep_order(t, primary) */ * from t force index(primary) where a<10 order by a limit 1;", + "explain select /*+ no_keep_order(t, primary) ignore_index(t, primary) */ * from t where a<10 order by a limit 1;", + + "explain select /*+ no_keep_order(t1, idx_a) use_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "explain select /*+ no_keep_order(t1, idx_a) */ * from t1 use index(idx_a) where a<10 order by a limit 1;", + "explain select /*+ no_keep_order(t1, idx_a) force_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "explain select /*+ no_keep_order(t1, idx_a) */ * from t1 force index(idx_a) where a<10 order by a limit 1;", + "explain select /*+ no_keep_order(t1, idx_a) ignore_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + + // Use the keep_order/ no_keep_order with the use_view hint at the same time + "explain select /*+ qb_name(qb, v) keep_order(t1@qb, idx_a) */ * from v", + "explain select /*+ qb_name(qb, v1) keep_order(t@qb, primary) */ * from v1", + "explain select /*+ qb_name(qb, v) no_keep_order(t1@qb, idx_a) */ * from v", + "explain select /*+ qb_name(qb, v1) no_keep_order(t@qb, primary) */ * from v1", + + // Use the keep_order/ no_keep_order with CTE at the same time + "explain WITH CTE AS (select /*+ keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "explain WITH CTE AS (select /*+ keep_order(t, primary) */ * from t where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "explain WITH CTE AS (select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "explain WITH CTE AS (select /*+ no_keep_order(t, primary) */ * from t where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;" ] }, { diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index 67fd9d86ba858..cb7b47742f619 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -4386,6 +4386,390 @@ " └─TableRangeScan_10 333.33 cop[tikv] table:t range:[-inf,10), keep order:false, stats:pseudo" ], "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t1, idx_b) */ * from t1 where b<10 order by b limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t1.b, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t1.b, offset:0, count:1", + " └─Selection_14 3323.33 cop[tikv] lt(test.t1.b, 10)", + " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1176]Key 'idx_b' doesn't exist in table 't1'" + ] + }, + { + "SQL": "explain select /*+ keep_order(t, idx_b) */ * from t where b<10 order by b limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t.b, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t.b, offset:0, count:1", + " └─Selection_14 3323.33 cop[tikv] lt(test.t.b, 10)", + " └─TableFullScan_13 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1176]Key 'idx_b' doesn't exist in table 't'" + ] + }, + { + "SQL": "explain select /*+ no_keep_order(t1, idx_b) */ * from t1 where b<10 order by b limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t1.b, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t1.b, offset:0, count:1", + " └─Selection_14 3323.33 cop[tikv] lt(test.t1.b, 10)", + " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1176]Key 'idx_b' doesn't exist in table 't1'" + ] + }, + { + "SQL": "explain select /*+ no_keep_order(t, idx_b) */ * from t where b<10 order by b limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t.b, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t.b, offset:0, count:1", + " └─Selection_14 3323.33 cop[tikv] lt(test.t.b, 10)", + " └─TableFullScan_13 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1176]Key 'idx_b' doesn't exist in table 't'" + ] + }, + { + "SQL": "explain select /*+ keep_order(t1, idx_a) use_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "Plan": [ + "Limit_12 1.00 root offset:0, count:1", + "└─Projection_19 1.00 root test.t1.a, test.t1.b", + " └─IndexLookUp_18 1.00 root ", + " ├─Limit_17(Build) 1.00 cop[tikv] offset:0, count:1", + " │ └─IndexRangeScan_13 1.00 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:true, stats:pseudo", + " └─TableRowIDScan_14(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t1, idx_a) */ * from t1 use index(idx_a) where a<10 order by a limit 1;", + "Plan": [ + "Limit_12 1.00 root offset:0, count:1", + "└─Projection_19 1.00 root test.t1.a, test.t1.b", + " └─IndexLookUp_18 1.00 root ", + " ├─Limit_17(Build) 1.00 cop[tikv] offset:0, count:1", + " │ └─IndexRangeScan_13 1.00 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:true, stats:pseudo", + " └─TableRowIDScan_14(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t1, idx_a) force_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "Plan": [ + "Limit_12 1.00 root offset:0, count:1", + "└─Projection_19 1.00 root test.t1.a, test.t1.b", + " └─IndexLookUp_18 1.00 root ", + " ├─Limit_17(Build) 1.00 cop[tikv] offset:0, count:1", + " │ └─IndexRangeScan_13 1.00 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:true, stats:pseudo", + " └─TableRowIDScan_14(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t1, idx_a) */ * from t1 force index(idx_a) where a<10 order by a limit 1;", + "Plan": [ + "Limit_12 1.00 root offset:0, count:1", + "└─Projection_19 1.00 root test.t1.a, test.t1.b", + " └─IndexLookUp_18 1.00 root ", + " ├─Limit_17(Build) 1.00 cop[tikv] offset:0, count:1", + " │ └─IndexRangeScan_13 1.00 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:true, stats:pseudo", + " └─TableRowIDScan_14(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t1, idx_a) ignore_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t1.a, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t1.a, offset:0, count:1", + " └─Selection_14 3323.33 cop[tikv] lt(test.t1.a, 10)", + " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t, primary) use_index(t, primary) */ * from t where a<10 order by a limit 1;", + "Plan": [ + "Limit_11 1.00 root offset:0, count:1", + "└─TableReader_16 1.00 root data:Limit_15", + " └─Limit_15 1.00 cop[tikv] offset:0, count:1", + " └─TableRangeScan_13 333.33 cop[tikv] table:t range:[-inf,10), keep order:true, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t, primary) */ * from t use index(primary) where a<10 order by a limit 1;", + "Plan": [ + "Limit_11 1.00 root offset:0, count:1", + "└─TableReader_16 1.00 root data:Limit_15", + " └─Limit_15 1.00 cop[tikv] offset:0, count:1", + " └─TableRangeScan_13 333.33 cop[tikv] table:t range:[-inf,10), keep order:true, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t, primary) force_index(t, primary) */ * from t where a<10 order by a limit 1;", + "Plan": [ + "Limit_11 1.00 root offset:0, count:1", + "└─TableReader_16 1.00 root data:Limit_15", + " └─Limit_15 1.00 cop[tikv] offset:0, count:1", + " └─TableRangeScan_13 333.33 cop[tikv] table:t range:[-inf,10), keep order:true, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t, primary) */ * from t force index(primary) where a<10 order by a limit 1;", + "Plan": [ + "Limit_11 1.00 root offset:0, count:1", + "└─TableReader_16 1.00 root data:Limit_15", + " └─Limit_15 1.00 cop[tikv] offset:0, count:1", + " └─TableRangeScan_13 333.33 cop[tikv] table:t range:[-inf,10), keep order:true, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ keep_order(t, primary) ignore_index(t, primary) */ * from t where a<10 order by a limit 1;", + "Plan": [ + "Limit_11 1.00 root offset:0, count:1", + "└─TableReader_15 1.00 root data:Limit_14", + " └─Limit_14 1.00 cop[tikv] offset:0, count:1", + " └─TableRangeScan_13 333.33 cop[tikv] table:t range:[-inf,10), keep order:true, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t, primary) use_index(t, primary) */ * from t where a<10 order by a limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t.a, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t.a, offset:0, count:1", + " └─TableRangeScan_13 3333.33 cop[tikv] table:t range:[-inf,10), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t, primary) */ * from t use index(primary) where a<10 order by a limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t.a, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t.a, offset:0, count:1", + " └─TableRangeScan_13 3333.33 cop[tikv] table:t range:[-inf,10), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t, primary) force_index(t, primary) */ * from t where a<10 order by a limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t.a, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t.a, offset:0, count:1", + " └─TableRangeScan_13 3333.33 cop[tikv] table:t range:[-inf,10), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t, primary) */ * from t force index(primary) where a<10 order by a limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t.a, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t.a, offset:0, count:1", + " └─TableRangeScan_13 3333.33 cop[tikv] table:t range:[-inf,10), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t, primary) ignore_index(t, primary) */ * from t where a<10 order by a limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t.a, offset:0, count:1", + "└─TableReader_15 1.00 root data:TopN_14", + " └─TopN_14 1.00 cop[tikv] test.t.a, offset:0, count:1", + " └─TableRangeScan_13 3333.33 cop[tikv] table:t range:[-inf,10), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t1, idx_a) use_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "Plan": [ + "TopN_9 1.00 root test.t1.a, offset:0, count:1", + "└─IndexLookUp_18 1.00 root ", + " ├─TopN_17(Build) 1.00 cop[tikv] test.t1.a, offset:0, count:1", + " │ └─IndexRangeScan_13 3323.33 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:false, stats:pseudo", + " └─TableRowIDScan_14(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t1, idx_a) */ * from t1 use index(idx_a) where a<10 order by a limit 1;", + "Plan": [ + "TopN_9 1.00 root test.t1.a, offset:0, count:1", + "└─IndexLookUp_18 1.00 root ", + " ├─TopN_17(Build) 1.00 cop[tikv] test.t1.a, offset:0, count:1", + " │ └─IndexRangeScan_13 3323.33 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:false, stats:pseudo", + " └─TableRowIDScan_14(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t1, idx_a) force_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "Plan": [ + "TopN_9 1.00 root test.t1.a, offset:0, count:1", + "└─IndexLookUp_18 1.00 root ", + " ├─TopN_17(Build) 1.00 cop[tikv] test.t1.a, offset:0, count:1", + " │ └─IndexRangeScan_13 3323.33 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:false, stats:pseudo", + " └─TableRowIDScan_14(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t1, idx_a) */ * from t1 force index(idx_a) where a<10 order by a limit 1;", + "Plan": [ + "TopN_9 1.00 root test.t1.a, offset:0, count:1", + "└─IndexLookUp_18 1.00 root ", + " ├─TopN_17(Build) 1.00 cop[tikv] test.t1.a, offset:0, count:1", + " │ └─IndexRangeScan_13 3323.33 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:false, stats:pseudo", + " └─TableRowIDScan_14(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ no_keep_order(t1, idx_a) ignore_index(t1, idx_a) */ * from t1 where a<10 order by a limit 1;", + "Plan": [ + "TopN_8 1.00 root test.t1.a, offset:0, count:1", + "└─TableReader_16 1.00 root data:TopN_15", + " └─TopN_15 1.00 cop[tikv] test.t1.a, offset:0, count:1", + " └─Selection_14 3323.33 cop[tikv] lt(test.t1.a, 10)", + " └─TableFullScan_13 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ qb_name(qb, v) keep_order(t1@qb, idx_a) */ * from v", + "Plan": [ + "Limit_14 1.00 root offset:0, count:1", + "└─Projection_19 1.00 root test.t1.a, test.t1.b", + " └─IndexLookUp_18 1.00 root ", + " ├─Limit_17(Build) 1.00 cop[tikv] offset:0, count:1", + " │ └─IndexRangeScan_15 1.00 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:true, stats:pseudo", + " └─TableRowIDScan_16(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ qb_name(qb, v1) keep_order(t@qb, primary) */ * from v1", + "Plan": [ + "Limit_13 1.00 root offset:0, count:1", + "└─TableReader_17 1.00 root data:Limit_16", + " └─Limit_16 1.00 cop[tikv] offset:0, count:1", + " └─TableRangeScan_15 333.33 cop[tikv] table:t range:[-inf,10), keep order:true, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ qb_name(qb, v) no_keep_order(t1@qb, idx_a) */ * from v", + "Plan": [ + "TopN_11 1.00 root test.t1.a, offset:0, count:1", + "└─IndexLookUp_18 1.00 root ", + " ├─TopN_17(Build) 1.00 cop[tikv] test.t1.a, offset:0, count:1", + " │ └─IndexRangeScan_15 3323.33 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:false, stats:pseudo", + " └─TableRowIDScan_16(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ qb_name(qb, v1) no_keep_order(t@qb, primary) */ * from v1", + "Plan": [ + "TopN_10 1.00 root test.t.a, offset:0, count:1", + "└─TableReader_17 1.00 root data:TopN_16", + " └─TopN_16 1.00 cop[tikv] test.t.a, offset:0, count:1", + " └─TableRangeScan_15 3333.33 cop[tikv] table:t range:[-inf,10), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain WITH CTE AS (select /*+ keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "HashAgg_30 2.00 root group by:Column#8, Column#9, funcs:firstrow(Column#8)->Column#8, funcs:firstrow(Column#9)->Column#9", + "└─Union_31 1.28 root ", + " ├─Selection_33 0.64 root lt(test.t1.a, 18)", + " │ └─CTEFullScan_34 0.80 root CTE:cte data:CTE_0", + " └─Selection_36 0.64 root gt(test.t1.b, 1)", + " └─CTEFullScan_37 0.80 root CTE:cte data:CTE_0", + "CTE_0 0.80 root Non-Recursive CTE", + "└─Selection_18(Seed Part) 0.80 root or(lt(test.t1.a, 18), gt(test.t1.b, 1))", + " └─Limit_24 1.00 root offset:0, count:1", + " └─Projection_29 1.00 root test.t1.a, test.t1.b", + " └─IndexLookUp_28 1.00 root ", + " ├─Limit_27(Build) 1.00 cop[tikv] offset:0, count:1", + " │ └─IndexRangeScan_25 1.00 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:true, stats:pseudo", + " └─TableRowIDScan_26(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain WITH CTE AS (select /*+ keep_order(t, primary) */ * from t where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "HashAgg_28 2.00 root group by:Column#7, Column#8, funcs:firstrow(Column#7)->Column#7, funcs:firstrow(Column#8)->Column#8", + "└─Union_29 1.28 root ", + " ├─Selection_31 0.64 root lt(test.t.a, 18)", + " │ └─CTEFullScan_32 0.80 root CTE:cte data:CTE_0", + " └─Selection_34 0.64 root gt(test.t.b, 1)", + " └─CTEFullScan_35 0.80 root CTE:cte data:CTE_0", + "CTE_0 0.80 root Non-Recursive CTE", + "└─Selection_18(Seed Part) 0.80 root or(lt(test.t.a, 18), gt(test.t.b, 1))", + " └─Limit_23 1.00 root offset:0, count:1", + " └─TableReader_27 1.00 root data:Limit_26", + " └─Limit_26 1.00 cop[tikv] offset:0, count:1", + " └─TableRangeScan_25 333.33 cop[tikv] table:t range:[-inf,10), keep order:true, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain WITH CTE AS (select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "HashAgg_29 2.00 root group by:Column#8, Column#9, funcs:firstrow(Column#8)->Column#8, funcs:firstrow(Column#9)->Column#9", + "└─Union_30 1.28 root ", + " ├─Selection_32 0.64 root lt(test.t1.a, 18)", + " │ └─CTEFullScan_33 0.80 root CTE:cte data:CTE_0", + " └─Selection_35 0.64 root gt(test.t1.b, 1)", + " └─CTEFullScan_36 0.80 root CTE:cte data:CTE_0", + "CTE_0 0.80 root Non-Recursive CTE", + "└─Selection_18(Seed Part) 0.80 root or(lt(test.t1.a, 18), gt(test.t1.b, 1))", + " └─TopN_21 1.00 root test.t1.a, offset:0, count:1", + " └─IndexLookUp_28 1.00 root ", + " ├─TopN_27(Build) 1.00 cop[tikv] test.t1.a, offset:0, count:1", + " │ └─IndexRangeScan_25 3323.33 cop[tikv] table:t1, index:idx_a(a) range:[-inf,10), keep order:false, stats:pseudo", + " └─TableRowIDScan_26(Probe) 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain WITH CTE AS (select /*+ no_keep_order(t, primary) */ * from t where a<10 order by a limit 1) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "HashAgg_28 2.00 root group by:Column#7, Column#8, funcs:firstrow(Column#7)->Column#7, funcs:firstrow(Column#8)->Column#8", + "└─Union_29 1.28 root ", + " ├─Selection_31 0.64 root lt(test.t.a, 18)", + " │ └─CTEFullScan_32 0.80 root CTE:cte data:CTE_0", + " └─Selection_34 0.64 root gt(test.t.b, 1)", + " └─CTEFullScan_35 0.80 root CTE:cte data:CTE_0", + "CTE_0 0.80 root Non-Recursive CTE", + "└─Selection_18(Seed Part) 0.80 root or(lt(test.t.a, 18), gt(test.t.b, 1))", + " └─TopN_20 1.00 root test.t.a, offset:0, count:1", + " └─TableReader_27 1.00 root data:TopN_26", + " └─TopN_26 1.00 cop[tikv] test.t.a, offset:0, count:1", + " └─TableRangeScan_25 3333.33 cop[tikv] table:t range:[-inf,10), keep order:false, stats:pseudo" + ], + "Warn": null } ] },