From 3781969effe879eb75d9d000b7bab0d7bc93fa76 Mon Sep 17 00:00:00 2001 From: YangKeao Date: Sat, 11 May 2024 14:19:09 +0800 Subject: [PATCH] This is an automated cherry-pick of #52542 Signed-off-by: ti-chi-bot --- cmd/explaintest/r/explain_easy.result | 4 + .../casetest/dag/testdata/plan_suite_out.json | 695 +++ .../hint/testdata/integration_suite_out.json | 1903 +++++++++ .../testdata/plan_suite_out.json | 3750 +++++++++++++++++ pkg/planner/core/integration_test.go | 2315 ++++++++++ planner/core/logical_plan_builder.go | 2 +- types/field_type.go | 10 +- 7 files changed, 8675 insertions(+), 4 deletions(-) create mode 100644 pkg/planner/core/casetest/dag/testdata/plan_suite_out.json create mode 100644 pkg/planner/core/casetest/hint/testdata/integration_suite_out.json create mode 100644 pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json create mode 100644 pkg/planner/core/integration_test.go diff --git a/cmd/explaintest/r/explain_easy.result b/cmd/explaintest/r/explain_easy.result index 3cf445e547a14..8252d57ea3e30 100644 --- a/cmd/explaintest/r/explain_easy.result +++ b/cmd/explaintest/r/explain_easy.result @@ -523,7 +523,11 @@ StreamAgg 1.00 root funcs:count(1)->Column#22 │ └─Projection 1.00 root Column#33, Column#34, Column#35, Column#14, Column#15, Column#16 │ └─HashAgg 1.00 root group by:test.test01.region_id, test.test01.show_date, test.test01.stat_date, funcs:firstrow(test.test01.stat_date)->Column#33, funcs:firstrow(test.test01.show_date)->Column#34, funcs:firstrow(test.test01.region_id)->Column#35, funcs:firstrow(test.test01.stat_date)->Column#14, funcs:firstrow(test.test01.show_date)->Column#15, funcs:firstrow(test.test01.region_id)->Column#16, funcs:count(1)->Column#39 │ └─TableReader 0.01 root data:Selection +<<<<<<< HEAD:cmd/explaintest/r/explain_easy.result │ └─Selection 0.01 cop[tikv] eq(test.test01.period, 1), ge(test.test01.stat_date, 20191202), gt(cast(test.test01.registration_num, bigint(20) BINARY), 0), le(test.test01.stat_date, 20191202) +======= + │ └─Selection 0.01 cop[tikv] eq(explain_easy.test01.period, 1), ge(explain_easy.test01.stat_date, 20191202), gt(cast(explain_easy.test01.registration_num, decimal(20,0) BINARY), 0), le(explain_easy.test01.stat_date, 20191202) +>>>>>>> 09c8f964cc5 (planner: fix the issue that UnionAll didn't handle the range bump case (#52542)):tests/integrationtest/r/explain_easy.result │ └─TableFullScan 10000.00 cop[tikv] table:test01 keep order:false, stats:pseudo └─TableReader(Probe) 2.00 root data:TableRangeScan └─TableRangeScan 2.00 cop[tikv] table:b range: decided by [Column#16], keep order:false, stats:pseudo diff --git a/pkg/planner/core/casetest/dag/testdata/plan_suite_out.json b/pkg/planner/core/casetest/dag/testdata/plan_suite_out.json new file mode 100644 index 0000000000000..e0fcf34eae5d4 --- /dev/null +++ b/pkg/planner/core/casetest/dag/testdata/plan_suite_out.json @@ -0,0 +1,695 @@ +[ + { + "Name": "TestDAGPlanBuilderSimpleCase", + "Cases": [ + { + "SQL": "select * from t t1 use index(c_d_e)", + "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))" + }, + { + "SQL": "select f from t use index() where f = 1", + "Best": "TableReader(Table(t)->Sel([eq(test.t.f, 1)]))" + }, + { + "SQL": "select a from t where a between 1 and 2 order by c", + "Best": "TableReader(Table(t))->Sort->Projection" + }, + { + "SQL": "select * from t where (t.c > 0 and t.c < 2) or (t.c > 4 and t.c < 6) or (t.c > 8 and t.c < 10) or (t.c > 12 and t.c < 14) or (t.c > 16 and t.c < 18)", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1] [5,5] [9,9] [13,13] [17,17]], Table(t))" + }, + { + "SQL": "select * from t where (t.c > 0 and t.c < 1) or (t.c > 2 and t.c < 3) or (t.c > 4 and t.c < 5) or (t.c > 6 and t.c < 7) or (t.c > 9 and t.c < 10)", + "Best": "Dual" + }, + { + "SQL": "select * from t where t.c = 1 and t.e = 1 order by t.b limit 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t))->TopN([test.t.b],0,1)" + }, + { + "SQL": "select * from t where t.e_str is null", + "Best": "IndexLookUp(Index(t.e_d_c_str_prefix)[[NULL,NULL]], Table(t))" + }, + { + "SQL": "select * from t where t.c is null", + "Best": "Dual" + }, + { + "SQL": "select * from t where t.c = 1 and t.e = 1 order by t.e limit 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t))->TopN([test.t.e],0,1)" + }, + { + "SQL": "select * from t where t.c = 1 and t.e = 1 order by t.d limit 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)])->Limit, Table(t))" + }, + { + "SQL": "select c from t where t.c = 1 and t.e = 1 order by t.d limit 1", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)])->Limit)->Limit->Projection" + }, + { + "SQL": "select c from t order by t.a limit 1", + "Best": "TableReader(Table(t)->Limit)->Limit->Projection" + }, + { + "SQL": "select c from t order by t.a + t.b limit 1", + "Best": "TableReader(Table(t)->TopN([plus(test.t.a, test.t.b)],0,1))->Projection->TopN([Column#14],0,1)->Projection->Projection" + }, + { + "SQL": "select c from t limit 1", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Limit)->Limit" + }, + { + "SQL": "select c from t where c = 1 limit 1", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]]->Limit)->Limit" + }, + { + "SQL": "select c from t where c = 1", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]])" + }, + { + "SQL": "select c from t order by c", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])" + }, + { + "SQL": "select c from t where c = 1 order by e", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Sort->Projection" + }, + { + "SQL": "select c, b from t where c = 1 limit 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Limit, Table(t))->Projection" + }, + { + "SQL": "select c, b from t where c = 1 and e = 1 and b = 1 limit 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t)->Sel([eq(test.t.b, 1)])->Limit)->Limit->Projection" + }, + { + "SQL": "select c from t where c = 1 order by d, c", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Sort->Projection" + }, + { + "SQL": "select c_str from t where e_str = '1' order by d_str, c_str", + "Best": "IndexLookUp(Index(t.e_d_c_str_prefix)[[\"1\",\"1\"]], Table(t))->Sort->Projection" + }, + { + "SQL": "select c from t where t.c = 1 and t.a > 1 order by t.d limit 1", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]]->Sel([gt(test.t.a, 1)])->Limit)->Limit->Projection" + }, + { + "SQL": "select c from t where t.c = 1 and t.d = 1 order by t.a limit 1", + "Best": "IndexReader(Index(t.c_d_e)[[1 1,1 1]]->TopN([test.t.a],0,1))->TopN([test.t.a],0,1)->Projection" + }, + { + "SQL": "select * from t where t.c = 1 and t.a > 1 order by t.d limit 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([gt(test.t.a, 1)])->Limit, Table(t))" + }, + { + "SQL": "select * from t use index(e_d_c_str_prefix) where t.c_str = 'abcdefghijk' and t.d_str = 'd' and t.e_str = 'e'", + "Best": "IndexLookUp(Index(t.e_d_c_str_prefix)[[\"e\" \"d\" \"abcdefghij\",\"e\" \"d\" \"abcdefghij\"]], Table(t)->Sel([eq(test.t.c_str, abcdefghijk)]))" + }, + { + "SQL": "select * from t use index(e_d_c_str_prefix) where t.e_str = b'1110000'", + "Best": "IndexLookUp(Index(t.e_d_c_str_prefix)[[\"p\",\"p\"]], Table(t))" + }, + { + "SQL": "select * from (select * from t use index() order by b) t left join t t1 on t.a=t1.a limit 10", + "Best": "IndexJoin{TableReader(Table(t)->Limit)->Limit->TableReader(Table(t))}(test.t.a,test.t.a)->Limit" + }, + { + "SQL": "select * from ((SELECT 1 a,3 b) UNION (SELECT 2,1) ORDER BY (SELECT 2)) t order by a,b", + "Best": "UnionAll{Dual->Projection->Dual->Projection}->HashAgg->Sort" + }, + { + "SQL": "select * from ((SELECT 1 a,6 b) UNION (SELECT 2,5) UNION (SELECT 2, 4) ORDER BY 1) t order by 1, 2", + "Best": "UnionAll{Dual->Projection->Dual->Projection->Dual->Projection}->HashAgg->Projection->Sort" + }, + { + "SQL": "select * from (select *, NULL as xxx from t) t order by xxx", + "Best": "TableReader(Table(t))->Projection" + }, + { + "SQL": "select * from t use index(f) where f = 1 and a = 1", + "Best": "PointGet(Index(t.f)[KindInt64 1])->Sel([eq(test.t.a, 1)])" + }, + { + "SQL": "select * from t2 use index(b) where b = 1 and a = 1", + "Best": "PointGet(Index(t2.b)[KindInt64 1])->Sel([eq(test.t2.a, 1)])" + }, + { + "SQL": "select f from t where a > 1", + "Best": "TableReader(Table(t))->Projection" + }, + { + "SQL": "select f from t where a > 1 limit 10", + "Best": "TableReader(Table(t)->Limit)->Limit" + } + ] + }, + { + "Name": "TestDAGPlanBuilderJoin", + "Cases": [ + { + "SQL": "select * from t t1 join t t2 on t1.a = t2.c_str", + "Best": "LeftHashJoin{TableReader(Table(t))->Projection->TableReader(Table(t))->Projection}(Column#25,Column#26)" + }, + { + "SQL": "select * from t t1 join t t2 on t1.b = t2.a", + "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.a)" + }, + { + "SQL": "select * from t t1 join t t2 on t1.a = t2.a join t t3 on t1.a = t3.a", + "Best": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select * from t t1 join t t2 on t1.a = t2.a join t t3 on t1.b = t3.a", + "Best": "LeftHashJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.b,test.t.a)" + }, + { + "SQL": "select * from t t1 join t t2 on t1.b = t2.a order by t1.a", + "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.a)" + }, + { + "SQL": "select * from t t1 join t t2 on t1.b = t2.a order by t1.a limit 1", + "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.a)->Limit" + }, + { + "SQL": "select /*+ TIDB_HJ(t1, t2) */ * from t t1 join t t2 on t1.b = t2.a order by t1.a limit 1", + "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.a)->TopN([test.t.a],0,1)" + }, + { + "SQL": "select * from t t1 left join t t2 on t1.b = t2.a where 1 = 1 limit 1", + "Best": "IndexJoin{TableReader(Table(t)->Limit)->Limit->TableReader(Table(t))}(test.t.b,test.t.a)->Limit" + }, + { + "SQL": "select * from t t1 join t t2 on t1.b = t2.a and t1.c = 1 and t1.d = 1 and t1.e = 1 order by t1.a limit 1", + "Best": "IndexJoin{PointGet(Index(t.c_d_e)[KindInt64 1 KindInt64 1 KindInt64 1])->TableReader(Table(t))}(test.t.b,test.t.a)->TopN([test.t.a],0,1)" + }, + { + "SQL": "select * from t t1 join t t2 on t1.b = t2.b join t t3 on t1.b = t3.b", + "Best": "LeftHashJoin{LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.b)->TableReader(Table(t))}(test.t.b,test.t.b)" + }, + { + "SQL": "select * from t t1 join t t2 on t1.a = t2.a order by t1.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select * from t t1 left outer join t t2 on t1.a = t2.a right outer join t t3 on t1.a = t3.a", + "Best": "MergeRightOuterJoin{MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select * from t t1 join t t2 on t1.a = t2.a join t t3 on t1.a = t3.a and t1.b = 1 and t3.c = 1", + "Best": "IndexJoin{IndexJoin{TableReader(Table(t)->Sel([eq(test.t.b, 1)]))->IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)->Projection" + }, + { + "SQL": "select * from t where t.c in (select b from t s where s.a = t.a)", + "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)(test.t.c,test.t.b)" + }, + { + "SQL": "select t.c in (select b from t s where s.a = t.a) from t", + "Best": "LeftHashJoin{IndexReader(Index(t.c_d_e)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.a)(test.t.c,test.t.b)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.b", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))->Sort}(test.t.a,test.t.b)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.a order by t2.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.b = t2.b order by t2.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->Sort->TableReader(Table(t))->Sort}(test.t.b,test.t.b)->Sort" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.a = t2.a order by t2.a desc", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2)*/ * from t t1, t t2 where t1.b = t2.b order by t2.b desc", + "Best": "MergeInnerJoin{TableReader(Table(t))->Sort->TableReader(Table(t))->Sort}(test.t.b,test.t.b)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a", + "Best": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.a = t2.b and t2.a = t3.b", + "Best": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))->Sort}(test.t.a,test.t.b)->Sort->TableReader(Table(t))->Sort}(test.t.a,test.t.b)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.c = t2.c and t1.d = t2.d and t3.c = t1.c and t3.d = t1.d", + "Best": "MergeInnerJoin{MergeInnerJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)(test.t.d,test.t.d)->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)(test.t.d,test.t.d)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1, t t2, t t3 where t1.c = t2.c and t1.d = t2.d and t3.c = t1.c and t3.d = t1.d order by t1.c", + "Best": "MergeInnerJoin{MergeInnerJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)(test.t.d,test.t.d)->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)(test.t.d,test.t.d)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1 left outer join t t2 on t1.a = t2.a left outer join t t3 on t2.a = t3.a", + "Best": "MergeLeftOuterJoin{MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Sort->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_SMJ(t1,t2,t3)*/ * from t t1 left outer join t t2 on t1.a = t2.a left outer join t t3 on t1.a = t3.a", + "Best": "MergeLeftOuterJoin{MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1, t t2 where t1.a = t2.a", + "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1, t t2 where t1.a = t2.c", + "Best": "IndexJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,NULL]], Table(t))}(test.t.a,test.t.c)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ t1.a , t2.a from t t1, t t2 where t1.a = t2.c", + "Best": "IndexJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t1, t2) */ t1.a, t2.a from t t1, t t2 where t1.a = t2.a order by t1.c", + "Best": "IndexJoin{IndexReader(Index(t.c_d_e)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.a)->Projection" + }, + { + "SQL": "select /*+ TIDB_INLJ(t1, t2) */ t1.a, t2.a from t t1, t t2 where t1.a = t2.a order by t2.c", + "Best": "IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.a)->Projection" + }, + { + "SQL": "select /*+ TIDB_INLJ(t1) */ t1.a , t2.a from t t1, t t2 where t1.a = t2.c", + "Best": "IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.c,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 left outer join t t2 on t1.a = t2.a and t2.b < 1", + "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t)->Sel([lt(test.t.b, 1)]))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 join t t2 on t1.d=t2.d and t2.c = 1", + "Best": "IndexJoin{IndexLookUp(Index(t.c_d_e)[[1 NULL,1 NULL]], Table(t))->TableReader(Table(t))}(test.t.d,test.t.d)->Projection" + }, + { + "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 left outer join t t2 on t1.a = t2.b", + "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.b)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 right outer join t t2 on t1.a = t2.b", + "Best": "RightHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.b)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 where t1.a in (select a from t t2)", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t1) */ * from t t1 where t1.a in (select a from t t2)", + "Best": "IndexJoin{TableReader(Table(t))->IndexReader(Index(t.f)[[NULL,+inf]])}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.c=t2.c and t1.f=t2.f", + "Best": "IndexJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,NULL]], Table(t))}(test.t.c,test.t.c)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.a = t2.a and t1.f=t2.f", + "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.f=t2.f and t1.a=t2.a", + "Best": "IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.a=t2.a and t2.a in (1, 2)", + "Best": "IndexJoin{BatchPointGet(Handle(t.a)[1 2])->TableReader(Table(t)->Sel([in(test.t.a, 1, 2)]))}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.b=t2.c and t1.b=1 and t2.d > t1.d-10 and t2.d < t1.d+10", + "Best": "IndexJoin{TableReader(Table(t)->Sel([eq(test.t.b, 1)]))->IndexLookUp(Index(t.c_d_e)[[1 NULL,1 NULL]], Table(t))}" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.b=t2.b and t1.c=1 and t2.c=1 and t2.d > t1.d-10 and t2.d < t1.d+10", + "Best": "LeftHashJoin{IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t))->IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t))}(test.t.b,test.t.b)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t2.c > t1.d-10 and t2.c < t1.d+10", + "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.b = t2.c and t2.c=1 and t2.d=2 and t2.e=4", + "Best": "RightHashJoin{PointGet(Index(t.c_d_e)[KindInt64 1 KindInt64 2 KindInt64 4])->TableReader(Table(t)->Sel([eq(test.t.b, 1)]))}->Projection" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t2.c=1 and t2.d=1 and t2.e > 10 and t2.e < 20", + "Best": "RightHashJoin{IndexLookUp(Index(t.c_d_e)[(1 1 10,1 1 20)], Table(t))->TableReader(Table(t))}->Projection" + } + ] + }, + { + "Name": "TestDAGPlanBuilderSubquery", + "Cases": [ + { + "SQL": "select * from t where exists (select s.a from t s having sum(s.a) = t.a )", + "Best": "LeftHashJoin{TableReader(Table(t))->Projection->IndexReader(Index(t.f)[[NULL,+inf]]->StreamAgg)->StreamAgg}(Column#27,Column#25)" + }, + { + "SQL": "select * from t where exists (select s.a from t s having sum(s.a) = t.a ) order by t.a", + "Best": "LeftHashJoin{TableReader(Table(t))->Projection->IndexReader(Index(t.f)[[NULL,+inf]]->StreamAgg)->StreamAgg}(Column#27,Column#25)->Sort" + }, + { + "SQL": "select * from t where a in (select s.a from t s) order by t.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)" + }, + { + "SQL": "select * from t where exists (select s.a from t s where s.c in (select c from t as k where k.d = s.d) having sum(s.a) = t.a )", + "Best": "LeftHashJoin{TableReader(Table(t))->Projection->MergeSemiJoin{IndexReader(Index(t.c_d_e)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.c,test.t.c)(test.t.d,test.t.d)->Projection->StreamAgg}(Column#39,Column#37)" + }, + { + "SQL": "select * from t where a in (select a from t) order by b", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Sort" + }, + { + "SQL": "select t.c in (select count(*) from t s, t t1 where s.a = t.a and s.a = t1.a) from t", + "Best": "Apply{IndexReader(Index(t.c_d_e)[[NULL,+inf]])->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->StreamAgg}->Projection" + }, + { + "SQL": "select (select count(*) from t s, t t1 where s.a = t.a and s.a = t1.a) from t", + "Best": "MergeLeftOuterJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Projection}(test.t.a,test.t.a)->Projection" + }, + { + "SQL": "select (select count(*) from t s, t t1 where s.a = t.a and s.a = t1.a) from t order by t.a", + "Best": "MergeLeftOuterJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Projection}(test.t.a,test.t.a)->Projection->Projection" + } + ] + }, + { + "Name": "TestDAGPlanTopN", + "Cases": [ + { + "SQL": "select * from t t1 left join t t2 on t1.b = t2.b left join t t3 on t2.b = t3.b order by t1.a limit 1", + "Best": "LeftHashJoin{LeftHashJoin{TableReader(Table(t)->Limit)->Limit->TableReader(Table(t))}(test.t.b,test.t.b)->TopN([test.t.a],0,1)->TableReader(Table(t))}(test.t.b,test.t.b)->TopN([test.t.a],0,1)" + }, + { + "SQL": "select * from t t1 left join t t2 on t1.b = t2.b left join t t3 on t2.b = t3.b order by t1.b limit 1", + "Best": "LeftHashJoin{LeftHashJoin{TableReader(Table(t)->TopN([test.t.b],0,1))->TopN([test.t.b],0,1)->TableReader(Table(t))}(test.t.b,test.t.b)->TopN([test.t.b],0,1)->TableReader(Table(t))}(test.t.b,test.t.b)->TopN([test.t.b],0,1)" + }, + { + "SQL": "select * from t t1 left join t t2 on t1.b = t2.b left join t t3 on t2.b = t3.b limit 1", + "Best": "LeftHashJoin{LeftHashJoin{TableReader(Table(t)->Limit)->Limit->TableReader(Table(t))}(test.t.b,test.t.b)->Limit->TableReader(Table(t))}(test.t.b,test.t.b)->Limit" + }, + { + "SQL": "select * from t where b = 1 and c = 1 order by c limit 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t)->Sel([eq(test.t.b, 1)]))->Limit" + }, + { + "SQL": "select * from t where c = 1 order by c limit 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Limit, Table(t))" + }, + { + "SQL": "select * from t order by a limit 1", + "Best": "TableReader(Table(t)->Limit)->Limit" + }, + { + "SQL": "select c from t order by c limit 1", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Limit)->Limit" + } + ] + }, + { + "Name": "TestDAGPlanBuilderBasePhysicalPlan", + "Cases": [ + { + "SQL": "select * from t order by b limit 1 for update", + "Best": "TableReader(Table(t)->TopN([test.t.b],0,1))->TopN([test.t.b],0,1)->Lock", + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`), limit_to_cop(@`sel_1`)" + }, + { + "SQL": "update t set a = 5 where b < 1 order by d limit 1", + "Best": "TableReader(Table(t)->Sel([lt(test.t.b, 1)])->TopN([test.t.d],0,1))->TopN([test.t.d],0,1)->Update", + "Hints": "use_index(@`upd_1` `test`.`t` ), no_order_index(@`upd_1` `test`.`t` `primary`), limit_to_cop(@`upd_1`)" + }, + { + "SQL": "update t set a = 5", + "Best": "TableReader(Table(t))->Update", + "Hints": "use_index(@`upd_1` `test`.`t` ), no_order_index(@`upd_1` `test`.`t` `primary`)" + }, + { + "SQL": "delete /*+ TIDB_INLJ(t1, t2) */ t1 from t t1, t t2 where t1.c=t2.c", + "Best": "IndexJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,NULL]], Table(t))}(test.t.c,test.t.c)->Delete", + "Hints": "inl_join(@`del_1` `test`.`t2`), use_index(@`del_1` `test`.`t1` ), no_order_index(@`del_1` `test`.`t1` `primary`), use_index(@`del_1` `test`.`t2` `c_d_e`), no_order_index(@`del_1` `test`.`t2` `c_d_e`)" + }, + { + "SQL": "delete /*+ TIDB_SMJ(t1, t2) */ from t1 using t t1, t t2 where t1.c=t2.c", + "Best": "MergeInnerJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t.c,test.t.c)->Delete", + "Hints": "merge_join(@`del_1` `test`.`t1`), use_index(@`del_1` `test`.`t1` `c_d_e`), order_index(@`del_1` `test`.`t1` `c_d_e`), use_index(@`del_1` `test`.`t2` `c_d_e`), order_index(@`del_1` `test`.`t2` `c_d_e`)" + }, + { + "SQL": "update /*+ TIDB_SMJ(t1, t2) */ t t1, t t2 set t1.c=1, t2.c=1 where t1.a=t2.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Update", + "Hints": "merge_join(@`upd_1` `test`.`t1`), use_index(@`upd_1` `test`.`t1` ), order_index(@`upd_1` `test`.`t1` `primary`), use_index(@`upd_1` `test`.`t2` ), order_index(@`upd_1` `test`.`t2` `primary`)" + }, + { + "SQL": "update /*+ TIDB_HJ(t1, t2) */ t t1, t t2 set t1.c=1, t2.c=1 where t1.a=t2.a", + "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Update", + "Hints": "hash_join(@`upd_1` `test`.`t1`), use_index(@`upd_1` `test`.`t1` ), no_order_index(@`upd_1` `test`.`t1` `primary`), use_index(@`upd_1` `test`.`t2` ), no_order_index(@`upd_1` `test`.`t2` `primary`)" + }, + { + "SQL": "delete from t where b < 1 order by d limit 1", + "Best": "TableReader(Table(t)->Sel([lt(test.t.b, 1)])->TopN([test.t.d],0,1))->TopN([test.t.d],0,1)->Delete", + "Hints": "use_index(@`del_1` `test`.`t` ), no_order_index(@`del_1` `test`.`t` `primary`), limit_to_cop(@`del_1`)" + }, + { + "SQL": "delete from t", + "Best": "TableReader(Table(t))->Delete", + "Hints": "use_index(@`del_1` `test`.`t` ), no_order_index(@`del_1` `test`.`t` `primary`)" + }, + { + "SQL": "delete from t use index(c_d_e) where b = 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t)->Sel([eq(test.t.b, 1)]))->Delete", + "Hints": "use_index(@`del_1` `test`.`t` `c_d_e`), no_order_index(@`del_1` `test`.`t` `c_d_e`)" + }, + { + "SQL": "insert into t select * from t where b < 1 order by d limit 1", + "Best": "TableReader(Table(t)->Sel([lt(test.t.b, 1)])->TopN([test.t.d],0,1))->TopN([test.t.d],0,1)->Insert", + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`), limit_to_cop(@`sel_1`)" + }, + { + "SQL": "insert into t (a, b, c, e, f, g) values(0,0,0,0,0,0)", + "Best": "Insert", + "Hints": "" + }, + { + "SQL": "select 1", + "Best": "Dual->Projection", + "Hints": "" + }, + { + "SQL": "select * from t where false", + "Best": "Dual", + "Hints": "" + }, + { + "SQL": "show tables", + "Best": "Show", + "Hints": "" + } + ] + }, + { + "Name": "TestDAGPlanBuilderUnion", + "Cases": [ + { + "SQL": "select * from t union all select * from t", + "Best": "UnionAll{TableReader(Table(t))->TableReader(Table(t))}" + }, + { + "SQL": "select * from t union all (select * from t) order by a ", + "Best": "UnionAll{TableReader(Table(t))->TableReader(Table(t))}->Sort" + }, + { + "SQL": "select * from t union all (select * from t) limit 1", + "Best": "UnionAll{TableReader(Table(t)->Limit)->Limit->TableReader(Table(t)->Limit)->Limit}->Limit" + }, + { + "SQL": "select a from t union all (select c from t) order by a limit 1", + "Best": "UnionAll{TableReader(Table(t)->Limit)->Limit->IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Limit)->Limit}->TopN([Column#25],0,1)" + } + ] + }, + { + "Name": "TestDAGPlanBuilderUnionScan", + "Cases": [ + { + "SQL": "select * from t", + "Best": "TableReader(Table(t))->UnionScan([])->Projection" + }, + { + "SQL": "select * from t where b = 1", + "Best": "TableReader(Table(t)->Sel([eq(test.t.b, 1)]))->UnionScan([eq(test.t.b, 1)])->Projection" + }, + { + "SQL": "select * from t where a = 1", + "Best": "TableReader(Table(t)->Sel([eq(test.t.a, 1)]))->UnionScan([eq(test.t.a, 1)])->Projection" + }, + { + "SQL": "select * from t where a = 1 order by a", + "Best": "TableReader(Table(t)->Sel([eq(test.t.a, 1)]))->UnionScan([eq(test.t.a, 1)])->Projection->Sort" + }, + { + "SQL": "select * from t where a = 1 order by b", + "Best": "TableReader(Table(t)->Sel([eq(test.t.a, 1)]))->UnionScan([eq(test.t.a, 1)])->Projection->Sort" + }, + { + "SQL": "select * from t where a = 1 limit 1", + "Best": "TableReader(Table(t)->Sel([eq(test.t.a, 1)]))->UnionScan([eq(test.t.a, 1)])->Limit" + }, + { + "SQL": "select * from t where c = 1", + "Best": "TableReader(Table(t)->Sel([eq(test.t.c, 1)]))->UnionScan([eq(test.t.c, 1)])->Projection" + }, + { + "SQL": "select c from t where c = 1", + "Best": "TableReader(Table(t)->Sel([eq(test.t.c, 1)]))->UnionScan([eq(test.t.c, 1)])->Projection" + } + ] + }, + { + "Name": "TestDAGPlanBuilderAgg", + "Cases": [ + { + "SQL": "select distinct b from t", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg" + }, + { + "SQL": "select count(*) from (select * from t order by b) t group by b", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg" + }, + { + "SQL": "select count(*), x from (select b as bbb, a + 1 as x from (select * from t order by b) t) t group by bbb", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg" + }, + { + "SQL": "select sum(a), avg(b + c) from t group by d", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg" + }, + { + "SQL": "select sum(distinct a), avg(b + c) from t group by d", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg" + }, + { + "SQL": "select sum(e), avg(e + c) from t where c = 1 group by (c + d)", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]]->HashAgg)->HashAgg" + }, + { + "SQL": "select sum(e), avg(e + c) from t where c = 1 group by c", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection->StreamAgg" + }, + { + "SQL": "select sum(e), avg(e + c) from t where c = 1 group by e", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection->HashAgg" + }, + { + "SQL": "select sum(e), avg(b + c) from t where c = 1 and e = 1 group by d", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t))->Projection->Projection->StreamAgg" + }, + { + "SQL": "select sum(e), avg(b + c) from t where c = 1 and b = 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]], Table(t)->Sel([eq(test.t.b, 1)]))->Projection->StreamAgg" + }, + { + "SQL": "select sum(e) as k, avg(b + c) from t where c = 1 and b = 1 and e = 1 group by d order by k", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t)->Sel([eq(test.t.b, 1)]))->Projection->Projection->StreamAgg->Sort" + }, + { + "SQL": "select sum(e) as k, avg(b + c) from t where c = 1 and b = 1 and e = 1 group by c order by k", + "Best": "IndexLookUp(Index(t.c_d_e)[[1,1]]->Sel([eq(test.t.e, 1)]), Table(t)->Sel([eq(test.t.b, 1)]))->Projection->Projection->StreamAgg->Sort" + }, + { + "SQL": "select sum(to_base64(e)) from t where c = 1", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection->StreamAgg" + }, + { + "SQL": "select (select count(1) k from t s where s.a = t.a having k != 0) from t", + "Best": "MergeLeftOuterJoin{TableReader(Table(t))->TableReader(Table(t))->Projection}(test.t.a,test.t.a)->Projection" + }, + { + "SQL": "select sum(to_base64(e)) from t group by e,d,c order by c", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])->Projection->StreamAgg->Projection" + }, + { + "SQL": "select sum(e+1) from t group by e,d,c order by c", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->StreamAgg)->StreamAgg->Projection" + }, + { + "SQL": "select sum(to_base64(e)) from t group by e,d,c order by c,e", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])->Projection->StreamAgg->Sort->Projection" + }, + { + "SQL": "select sum(e+1) from t group by e,d,c order by c,e", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->StreamAgg)->StreamAgg->Sort->Projection" + }, + { + "SQL": "select count(*) from t group by g order by g limit 10", + "Best": "IndexReader(Index(t.g)[[NULL,+inf]]->StreamAgg)->StreamAgg->Limit->Projection" + }, + { + "SQL": "select count(*) from t group by g limit 10", + "Best": "IndexReader(Index(t.g)[[NULL,+inf]]->StreamAgg)->StreamAgg->Limit" + }, + { + "SQL": "select count(*) from t group by g order by g", + "Best": "IndexReader(Index(t.g)[[NULL,+inf]]->StreamAgg)->StreamAgg->Projection" + }, + { + "SQL": "select count(*) from t group by g order by g desc limit 1", + "Best": "IndexReader(Index(t.g)[[NULL,+inf]]->StreamAgg)->StreamAgg->Limit->Projection" + }, + { + "SQL": "select count(*) from t group by b order by b limit 10", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg->TopN([test.t.b],0,10)->Projection" + }, + { + "SQL": "select count(*) from t group by b order by b", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg->Sort->Projection" + }, + { + "SQL": "select count(*) from t group by b limit 10", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg->Limit" + }, + { + "SQL": "select sum(a.g), sum(b.g) from t a join t b on a.g = b.g group by a.g", + "Best": "MergeInnerJoin{IndexReader(Index(t.g)[[NULL,+inf]])->IndexReader(Index(t.g)[[NULL,+inf]])}(test.t.g,test.t.g)->Projection->StreamAgg" + }, + { + "SQL": "select /*+ tidb_inlj(a,b) */ sum(a.g), sum(b.g) from t a join t b on a.g = b.g and a.g > 60 group by a.g order by a.g limit 1", + "Best": "IndexJoin{IndexReader(Index(t.g)[(60,+inf]])->IndexReader(Index(t.g)[[NULL,NULL]]->Sel([gt(test.t.g, 60)]))}(test.t.g,test.t.g)->Projection->StreamAgg->Limit->Projection" + }, + { + "SQL": "select sum(a.g), sum(b.g) from t a join t b on a.g = b.g and a.a>5 group by a.g order by a.g limit 1", + "Best": "MergeInnerJoin{IndexReader(Index(t.g)[[NULL,+inf]]->Sel([gt(test.t.a, 5)]))->IndexReader(Index(t.g)[[NULL,+inf]])}(test.t.g,test.t.g)->Projection->StreamAgg->Limit->Projection" + }, + { + "SQL": "select sum(d) from t", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->StreamAgg)->StreamAgg" + } + ] + }, + { + "Name": "TestDAGPlanBuilderWindow", + "Cases": [ + { + "SQL": "select lead(a, 1) over (partition by null) as c from t", + "Best": "IndexReader(Index(t.f)[[NULL,+inf]])->Window(lead(test.t.a, 1)->Column#14 over())->Projection" + } + ] + }, + { + "Name": "TestDAGPlanBuilderWindowParallel", + "Cases": [ + { + "SQL": "select lead(a, 1) over (partition by null) as c from t", + "Best": "IndexReader(Index(t.f)[[NULL,+inf]])->Window(lead(test.t.a, 1)->Column#14 over())->Projection" + }, + { + "SQL": "select lead(a, 1) over (partition by b) as c from t", + "Best": "TableReader(Table(t))->Sort->Window(lead(test.t.a, 1)->Column#14 over(partition by test.t.b))->Partition(execution info: concurrency:4, data sources:[TableReader_10])->Projection" + } + ] + } +] diff --git a/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json b/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json new file mode 100644 index 0000000000000..db7113f881942 --- /dev/null +++ b/pkg/planner/core/casetest/hint/testdata/integration_suite_out.json @@ -0,0 +1,1903 @@ +[ + { + "Name": "TestOptimizeHintOnPartitionTable", + "Cases": [ + { + "SQL": "select /*+ use_index(t) */ * from t", + "Plan": [ + "PartitionUnion 30000.00 root ", + "├─TableReader 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t, partition:p0 keep order:false, stats:pseudo", + "├─TableReader 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t, partition:p1 keep order:false, stats:pseudo", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t, partition:p2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ use_index(t partition(p0, p1) b, c) */ * from t partition(p1,p2)", + "Plan": [ + "PartitionUnion 20000.00 root ", + "├─IndexLookUp 10000.00 root ", + "│ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, partition:p1, index:b(b) keep order:false, stats:pseudo", + "│ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t, partition:p1 keep order:false, stats:pseudo", + "└─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t, partition:p2 keep order:false, stats:pseudo" + ], + "Warn": [ + "Warning 1105 unknown partitions (p0) in optimizer hint /*+ USE_INDEX(t PARTITION(p0, p1) b, c) */" + ] + }, + { + "SQL": "select /*+ use_index(t partition(p_non_exist)) */ * from t partition(p1,p2)", + "Plan": [ + "PartitionUnion 20000.00 root ", + "├─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "│ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─TableFullScan 10000.00 mpp[tiflash] table:t, partition:p1 keep order:false, stats:pseudo", + "└─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t, partition:p2 keep order:false, stats:pseudo" + ], + "Warn": [ + "Warning 1105 unknown partitions (p_non_exist) in optimizer hint /*+ USE_INDEX(t PARTITION(p_non_exist)) */" + ] + }, + { + "SQL": "select /*+ use_index(t partition(p0, p1) b, c) */ * from t", + "Plan": [ + "PartitionUnion 30000.00 root ", + "├─IndexLookUp 10000.00 root ", + "│ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, partition:p0, index:b(b) keep order:false, stats:pseudo", + "│ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t, partition:p0 keep order:false, stats:pseudo", + "├─IndexLookUp 10000.00 root ", + "│ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, partition:p1, index:b(b) keep order:false, stats:pseudo", + "│ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t, partition:p1 keep order:false, stats:pseudo", + "└─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t, partition:p2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ ignore_index(t partition(p0, p1) b, c) */ * from t", + "Plan": [ + "PartitionUnion 30000.00 root ", + "├─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "│ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─TableFullScan 10000.00 mpp[tiflash] table:t, partition:p0 keep order:false, stats:pseudo", + "├─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "│ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─TableFullScan 10000.00 mpp[tiflash] table:t, partition:p1 keep order:false, stats:pseudo", + "└─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t, partition:p2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ hash_join(t1, t2 partition(p0)) */ * from t t1 join t t2 on t1.a = t2.a", + "Plan": [ + "HashJoin 37500.00 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─PartitionUnion(Build) 30000.00 root ", + "│ ├─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "│ │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + "│ │ └─TableFullScan 10000.00 mpp[tiflash] table:t2, partition:p0 keep order:false, stats:pseudo", + "│ ├─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "│ │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + "│ │ └─TableFullScan 10000.00 mpp[tiflash] table:t2, partition:p1 keep order:false, stats:pseudo", + "│ └─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "│ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─TableFullScan 10000.00 mpp[tiflash] table:t2, partition:p2 keep order:false, stats:pseudo", + "└─PartitionUnion(Probe) 30000.00 root ", + " ├─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1, partition:p0 keep order:false, stats:pseudo", + " ├─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1, partition:p1 keep order:false, stats:pseudo", + " └─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1, partition:p2 keep order:false, stats:pseudo" + ], + "Warn": [ + "Warning 1105 Optimizer Hint /*+ HASH_JOIN(t1, t2 PARTITION(p0)) */ is inapplicable on specified partitions" + ] + }, + { + "SQL": "select /*+ use_index_merge(t partition(p0)) */ * from t where t.b = 1 or t.c = \"8\"", + "Plan": [ + "PartitionUnion 59.97 root ", + "├─IndexMerge 19.99 root type: union", + "│ ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, partition:p0, index:b(b) range:[1,1], keep order:false, stats:pseudo", + "│ ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, partition:p0, index:c(c) range:[\"8\",\"8\"], keep order:false, stats:pseudo", + "│ └─TableRowIDScan(Probe) 19.99 cop[tikv] table:t, partition:p0 keep order:false, stats:pseudo", + "├─TableReader 19.99 root MppVersion: 2, data:ExchangeSender", + "│ └─ExchangeSender 19.99 mpp[tiflash] ExchangeType: PassThrough", + "│ └─TableFullScan 19.99 mpp[tiflash] table:t, partition:p1 pushed down filter:or(eq(test.t.b, 1), eq(test.t.c, \"8\")), keep order:false, stats:pseudo", + "└─TableReader 19.99 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 19.99 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 19.99 mpp[tiflash] table:t, partition:p2 pushed down filter:or(eq(test.t.b, 1), eq(test.t.c, \"8\")), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ use_index_merge(t partition(p0, p1) primary, b) */ * from t where t.a = 1 or t.b = 2", + "Plan": [ + "PartitionUnion 33.00 root ", + "├─IndexMerge 11.00 root type: union", + "│ ├─TableRangeScan(Build) 1.00 cop[tikv] table:t, partition:p0 range:[1,1], keep order:false, stats:pseudo", + "│ ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, partition:p0, index:b(b) range:[2,2], keep order:false, stats:pseudo", + "│ └─TableRowIDScan(Probe) 11.00 cop[tikv] table:t, partition:p0 keep order:false, stats:pseudo", + "├─IndexMerge 11.00 root type: union", + "│ ├─TableRangeScan(Build) 1.00 cop[tikv] table:t, partition:p1 range:[1,1], keep order:false, stats:pseudo", + "│ ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, partition:p1, index:b(b) range:[2,2], keep order:false, stats:pseudo", + "│ └─TableRowIDScan(Probe) 11.00 cop[tikv] table:t, partition:p1 keep order:false, stats:pseudo", + "└─TableReader 11.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 11.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 11.00 mpp[tiflash] table:t, partition:p2 pushed down filter:or(eq(test.t.a, 1), eq(test.t.b, 2)), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ use_index(t partition(p0) b) */ * from t partition(p0, p1)", + "Plan": [ + "PartitionUnion 20000.00 root ", + "├─IndexLookUp 10000.00 root ", + "│ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, partition:p0, index:b(b) keep order:false, stats:pseudo", + "│ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t, partition:p0 keep order:false, stats:pseudo", + "└─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t, partition:p1 keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, + { + "Name": "TestReadFromStorageHint", + "Cases": [ + { + "SQL": "desc format = 'brief' select avg(a) from t", + "Plan": [ + "HashAgg 1.00 root funcs:avg(Column#5, Column#6)->Column#4", + "└─TableReader 1.00 root data:HashAgg", + " └─HashAgg 1.00 batchCop[tiflash] funcs:count(Column#9)->Column#5, funcs:sum(Column#10)->Column#6", + " └─Projection 10000.00 batchCop[tiflash] test.t.a->Column#9, cast(test.t.a, decimal(10,0) BINARY)->Column#10", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t", + "Plan": [ + "HashAgg 1.00 root funcs:avg(Column#5, Column#6)->Column#4", + "└─TableReader 1.00 root data:HashAgg", + " └─HashAgg 1.00 batchCop[tiflash] funcs:count(Column#9)->Column#5, funcs:sum(Column#10)->Column#6", + " └─Projection 10000.00 batchCop[tiflash] test.t.a->Column#9, cast(test.t.a, decimal(10,0) BINARY)->Column#10", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:sum(Column#6)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#7)->Column#6", + " └─Projection 10000.00 batchCop[tiflash] cast(test.t.a, decimal(10,0) BINARY)->Column#7", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(a+1) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:sum(Column#6)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#7)->Column#6", + " └─Projection 10000.00 batchCop[tiflash] cast(plus(test.t.a, 1), decimal(20,0) BINARY)->Column#7", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ sum(isnull(a)) from t", + "Plan": [ + "StreamAgg 1.00 root funcs:sum(Column#6)->Column#4", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:sum(Column#7)->Column#6", + " └─Projection 10000.00 batchCop[tiflash] cast(isnull(test.t.a), decimal(20,0) BINARY)->Column#7", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIKV[t2]) */ * from t t1, t t2 where t1.a = t2.a", + "Plan": [ + "HashJoin 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─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.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ READ_FROM_STORAGE(TIKV[t1], TIFLASH[t2]) */ * from t t1, t t2 where t1.a = t2.a", + "Plan": [ + "HashJoin 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tiflash] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", + "Plan": [ + "TableReader 44.00 root data:TableRangeScan", + "└─TableRangeScan 44.00 cop[tikv] table:tt range:(1,20), [30,55), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[tt]) */ * from tt where (tt.a > 1 and tt.a < 20) or (tt.a >= 30 and tt.a < 55)", + "Plan": [ + "TableReader 44.00 root data:TableRangeScan", + "└─TableRangeScan 44.00 cop[tiflash] table:tt range:(1,20), [30,55), keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select * from ttt order by ttt.a desc", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:ttt keep order:true, desc, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a desc", + "Plan": [ + "Sort 10000.00 root test.ttt.a:desc", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:ttt keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[ttt]) */ * from ttt order by ttt.a", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tiflash] table:ttt keep order:true, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tikv[t, ttt]) */ * from ttt", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:ttt keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]There are no matching table names for (t) in optimizer hint /*+ READ_FROM_STORAGE(tikv[t, ttt]) */. Maybe you can use the table alias name" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t, ttt], tikv[tt]) */ * from ttt", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tiflash] table:ttt keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]There are no matching table names for (t, tt) in optimizer hint /*+ READ_FROM_STORAGE(tiflash[t, ttt], tikv[tt]) */. Maybe you can use the table alias name" + ] + } + ] + }, + { + "Name": "TestAllViewHintType", + "Cases": [ + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(@qb_v1 v, t2) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]leading hint is inapplicable, check if the leading hint table is valid" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(v@qb_v1, t2@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]leading hint is inapplicable, check if the leading hint table is valid" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(@qb_v1 t3, t2) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(t3@qb_v1, t2@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), qb_name(qb_v, v1.v), leading(t2@qb_v1, t@qb_v) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Only one query block name is allowed in a view hint, otherwise the hint will be invalid" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join(@qb_v1 v, t2) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t3.a, test.t.a)]", + "├─MergeJoin(Build) 12500.00 root inner join, left key:test.t.a, right key:test.t1.a", + "│ ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + "│ └─IndexReader(Probe) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + "└─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join(t2@qb_v1, t3@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join_build(@qb_v1 v) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t3.a, test.t.a)]", + "├─MergeJoin(Build) 12500.00 root inner join, left key:test.t.a, right key:test.t1.a", + "│ ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + "│ └─IndexReader(Probe) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + "└─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join_build(t2@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " │ └─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.t3.a)), not(isnull(test.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join_build(@qb_v1 v) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t3.a, test.t.a)]", + "├─MergeJoin(Build) 12500.00 root inner join, left key:test.t.a, right key:test.t1.a", + "│ ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + "│ └─IndexReader(Probe) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + "└─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join_build(t2@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " │ └─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.t3.a)), not(isnull(test.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), merge_join(@qb_v1 v) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t3.a, test.t.a)]", + "├─MergeJoin(Build) 12500.00 root inner join, left key:test.t.a, right key:test.t1.a", + "│ ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + "│ └─IndexReader(Probe) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + "└─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), merge_join(t2@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t3.b, right key:test.t2.b", + " ├─Sort(Build) 9990.00 root test.t2.b", + " │ └─TableReader 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─Sort(Probe) 9980.01 root test.t3.b", + " └─TableReader 9980.01 root data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v, v), INL_JOIN(@qb_v t) */ * from v;", + "Plan": [ + "IndexJoin 12500.00 root inner join, inner:IndexLookUp, outer key:test.t1.a, inner key:test.t.a, equal cond:eq(test.t1.a, test.t.a)", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 12500.00 root ", + " ├─IndexRangeScan(Build) 12500.00 cop[tikv] table:t, index:idx_a(a) range: decided by [eq(test.t.a, test.t1.a)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 12500.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v, v), INL_JOIN(t@qb_v) */ * from v;", + "Plan": [ + "IndexJoin 12500.00 root inner join, inner:IndexLookUp, outer key:test.t1.a, inner key:test.t.a, equal cond:eq(test.t1.a, test.t.a)", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 12500.00 root ", + " ├─IndexRangeScan(Build) 12500.00 cop[tikv] table:t, index:idx_a(a) range: decided by [eq(test.t.a, test.t1.a)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 12500.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v2, v2.@sel_2), hash_agg(@qb_v2) */ * from v2;", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#19)]", + "├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ └─HashJoin 24365.26 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "│ ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 19492.21 root inner join, equal:[eq(test.t3.a, test.t.a)]", + "│ ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + "│ │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + "│ │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 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", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v2, v2.@sel_2), stream_agg(@qb_v2) */ * from v2;", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#19)]", + "├─StreamAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ └─Sort 24365.26 root test.t2.a", + "│ └─HashJoin 24365.26 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "│ ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 19492.21 root inner join, equal:[eq(test.t3.a, test.t.a)]", + "│ ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + "│ │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + "│ │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 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", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), use_index(t5@qb_v3, idx_a) */ * from v3;", + "Plan": [ + "IndexLookUp 1107.78 root ", + "├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t5, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo", + "└─Selection(Probe) 1107.78 cop[tikv] lt(test.t5.b, 2)", + " └─TableRowIDScan 3333.33 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), use_index(@qb_v3 t5, idx_b) */ * from v3;", + "Plan": [ + "IndexLookUp 1107.78 root ", + "├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t5, index:idx_b(b) range:[-inf,2), keep order:false, stats:pseudo", + "└─Selection(Probe) 1107.78 cop[tikv] gt(test.t5.a, 1)", + " └─TableRowIDScan 3323.33 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), force_index(t5@qb_v3, idx_a) */ * from v3;", + "Plan": [ + "IndexLookUp 1107.78 root ", + "├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t5, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo", + "└─Selection(Probe) 1107.78 cop[tikv] lt(test.t5.b, 2)", + " └─TableRowIDScan 3333.33 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), force_index(@qb_v3 t5, idx_b) */ * from v3;", + "Plan": [ + "IndexLookUp 1107.78 root ", + "├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t5, index:idx_b(b) range:[-inf,2), keep order:false, stats:pseudo", + "└─Selection(Probe) 1107.78 cop[tikv] gt(test.t5.a, 1)", + " └─TableRowIDScan 3323.33 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), ignore_index(t5@qb_v3, idx_a) */ * from v3;", + "Plan": [ + "TableReader 1107.78 root data:Selection", + "└─Selection 1107.78 cop[tikv] gt(test.t5.a, 1), lt(test.t5.b, 2)", + " └─TableFullScan 10000.00 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), ignore_index(@qb_v3 t5, idx_b) */ * from v3;", + "Plan": [ + "TableReader 1107.78 root data:Selection", + "└─Selection 1107.78 cop[tikv] gt(test.t5.a, 1), lt(test.t5.b, 2)", + " └─TableFullScan 10000.00 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v4, v4), use_index_merge(t5@qb_v4, idx_a, idx_b) */ * from v4;", + "Plan": [ + "IndexMerge 5548.89 root type: union", + "├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t5, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo", + "├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t5, index:idx_b(b) range:[-inf,2), keep order:false, stats:pseudo", + "└─TableRowIDScan(Probe) 5548.89 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v4, v4), use_index_merge(@qb_v4 t5, idx_b, idx_a) */ * from v4;", + "Plan": [ + "IndexMerge 5548.89 root type: union", + "├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t5, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo", + "├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t5, index:idx_b(b) range:[-inf,2), keep order:false, stats:pseudo", + "└─TableRowIDScan(Probe) 5548.89 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v, v), READ_FROM_STORAGE(TIFLASH[t@qb_v], TIKV[t1@qb_v]) */ * from v;", + "Plan": [ + "HashJoin 12500.00 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v5, v5.@sel_2), SEMI_JOIN_REWRITE(@qb_v5) */ * from v5;", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "├─HashAgg(Build) 7992.00 root group by:test.t1.b, funcs:firstrow(test.t1.b)->test.t1.b", + "│ └─TableReader 7992.00 root data:HashAgg", + "│ └─HashAgg 7992.00 cop[tikv] group by:test.t1.b, ", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v6, v6.@sel_2), NO_DECORRELATE(@qb_v6) */ * from v6;", + "Plan": [ + "Projection 10000.00 root test.t1.a, test.t1.b", + "└─Apply 10000.00 root CARTESIAN inner join, other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#7)", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─MaxOneRow(Probe) 10000.00 root ", + " └─StreamAgg 10000.00 root funcs:sum(Column#9)->Column#7", + " └─TableReader 10000.00 root data:StreamAgg", + " └─StreamAgg 10000.00 cop[tikv] funcs:sum(test.t2.a)->Column#9", + " └─Selection 100000.00 cop[tikv] eq(test.t2.b, test.t1.b)", + " └─TableFullScan 100000000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v7, v7), merge(@qb_v7) */ * from v7;", + "Plan": [ + "TableReader 3544.89 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 3544.89 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 3544.89 mpp[tiflash] Column#14, Column#15", + " └─HashAgg 3544.89 mpp[tiflash] group by:Column#14, Column#15, funcs:firstrow(Column#14)->Column#14, funcs:firstrow(Column#15)->Column#15", + " └─ExchangeReceiver 3544.89 mpp[tiflash] ", + " └─ExchangeSender 3544.89 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#14, collate: binary], [name: Column#15, collate: binary]", + " └─HashAgg 3544.89 mpp[tiflash] group by:Column#14, Column#15, ", + " └─Union 4431.11 mpp[tiflash] ", + " ├─Selection 3323.33 mpp[tiflash] lt(test.t.a, 18), lt(test.t.a, 60)", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection 1107.78 mpp[tiflash] gt(test.t.b, 1), lt(test.t.a, 60)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v8, v8), merge(@qb_v8) */ * from v8;", + "Plan": [ + "HashAgg 16000.00 root group by:Column#41, funcs:firstrow(Column#41)->Column#41", + "└─Union 1000000010000.00 root ", + " ├─HashJoin 1000000000000.00 root CARTESIAN inner join", + " │ ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " │ └─Projection(Probe) 100000000.00 root 1->Column#55", + " │ └─HashJoin 100000000.00 root CARTESIAN inner join", + " │ ├─Projection(Build) 10000.00 root 1->Column#54", + " │ │ └─IndexReader 10000.00 root index:IndexFullScan", + " │ │ └─IndexFullScan 10000.00 cop[tikv] table:t3, index:idx_a(a) keep order:false, stats:pseudo", + " │ └─Projection(Probe) 10000.00 root 1->Column#53", + " │ └─IndexReader 10000.00 root index:IndexFullScan", + " │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:idx_a(a) keep order:false, stats:pseudo", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v9, v9), AGG_TO_COP(@qb_v9) */ * from v9;", + "Plan": [ + "HashAgg 1.00 root funcs:sum(Column#6)->Column#4", + "└─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#9)->Column#6", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.a, decimal(10,0) BINARY)->Column#9", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v10, v10), LIMIT_TO_COP(@qb_v10) */ * from v10;", + "Plan": [ + "TopN 1.00 root test.t.b, offset:0, count:1", + "└─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TopN 1.00 mpp[tiflash] test.t.b, offset:0, count:1", + " └─Selection 3333.33 mpp[tiflash] gt(test.t.a, 10)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb, v11) read_from_storage(tiflash[t@qb]), MPP_1PHASE_AGG(@qb) */ * from v11;", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#4", + " └─Projection 8000.00 mpp[tiflash] Column#4, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#7, funcs:sum(Column#5)->Column#4, funcs:firstrow(Column#6)->test.t.a", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#5, test.t.a->Column#6, test.t.a->Column#7", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb, v11) read_from_storage(tiflash[t@qb]), MPP_2PHASE_AGG(@qb) */ * from v11;", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#4", + " └─Projection 8000.00 mpp[tiflash] Column#4, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.a, funcs:sum(Column#7)->Column#4, funcs:firstrow(test.t.a)->test.t.a", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#10, funcs:sum(Column#9)->Column#7", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#9, test.t.a->Column#10", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb, v12) read_from_storage(tiflash[t1@qb, t@qb]), shuffle_join(t1@qb, t@qb) */ * from v12;", + "Plan": [ + "TableReader 12500.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12500.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12500.00 mpp[tiflash] test.t.a, test.t.b", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb, v12) read_from_storage(tiflash[t1@qb, t@qb]), broadcast_join(t1@qb, t@qb) */ * from v12;", + "Plan": [ + "TableReader 12500.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12500.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12500.00 mpp[tiflash] test.t.a, test.t.b", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, + { + "Name": "TestJoinHintCompatibility", + "Cases": [ + { + "SQL": "explain format = 'brief' select /*+ leading(t3), hash_join(t1) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ └─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.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2), hash_join(t2) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ └─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.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t3), merge_join(t1) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─MergeJoin 15593.77 root inner join, left key:test.t2.a, right key:test.t1.a", + " ├─Projection(Build) 10000.00 root test.t1.a, test.t1.b", + " │ └─IndexLookUp 10000.00 root ", + " │ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " │ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─Sort(Probe) 12475.01 root test.t2.a", + " └─HashJoin 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ └─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.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2), merge_join(t2) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t2.b, right key:test.t3.b", + " ├─Projection(Build) 9990.00 root test.t3.a, test.t3.b", + " │ └─IndexLookUp 9990.00 root ", + " │ ├─IndexFullScan(Build) 9990.00 cop[tikv] table:t3, index:idx_b(b) keep order:true, stats:pseudo", + " │ └─TableRowIDScan(Probe) 9990.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─Projection(Probe) 9980.01 root test.t2.a, test.t2.b", + " └─IndexLookUp 9980.01 root ", + " ├─IndexFullScan(Build) 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, stats:pseudo", + " └─Selection(Probe) 9980.01 cop[tikv] not(isnull(test.t2.a))", + " └─TableRowIDScan 9990.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t3), inl_join(t1) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─IndexJoin 15593.77 root inner join, inner:IndexLookUp, outer key:test.t2.a, inner key:test.t1.a, equal cond:eq(test.t2.a, test.t1.a)", + " ├─HashJoin(Build) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " │ ├─TableReader(Build) 9980.01 root data:Selection", + " │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ │ └─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.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─IndexLookUp(Probe) 15593.77 root ", + " ├─IndexRangeScan(Build) 15593.77 cop[tikv] table:t1, index:idx_a(a) range: decided by [eq(test.t1.a, test.t2.a)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 15593.77 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2), inl_join(t2) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─IndexJoin(Probe) 12475.01 root inner join, inner:IndexLookUp, outer key:test.t3.b, inner key:test.t2.b, equal cond:eq(test.t3.b, test.t2.b)", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─IndexLookUp(Probe) 12475.01 root ", + " ├─Selection(Build) 12487.50 cop[tikv] not(isnull(test.t2.b))", + " │ └─IndexRangeScan 12500.00 cop[tikv] table:t2, index:idx_b(b) range: decided by [eq(test.t2.b, test.t3.b)], keep order:false, stats:pseudo", + " └─Selection(Probe) 12475.01 cop[tikv] not(isnull(test.t2.a))", + " └─TableRowIDScan 12487.50 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t3), hash_join_build(t1) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ └─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.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2), hash_join_build(t2) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ └─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.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t3), hash_join_probe(t1) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─HashJoin(Build) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " │ ├─TableReader(Build) 9980.01 root data:Selection", + " │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ │ └─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.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2), hash_join_probe(t2) */ * from t1 join t2 join t3 where t1.a = t2.a and t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9980.01 root data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t6), shuffle_join(t4) */ * from t4 join t5 join t6 where t4.a = t5.a and t5.b = t6.b;", + "Plan": [ + "TableReader 15593.77 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 15593.77 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 15593.77 mpp[tiflash] test.t4.a, test.t4.b, test.t5.a, test.t5.b, test.t6.a, test.t6.b", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t5.a, test.t4.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t4.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t4.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t4 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 12475.01 mpp[tiflash] ", + " └─ExchangeSender 12475.01 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t5.a, collate: binary]", + " └─HashJoin 12475.01 mpp[tiflash] inner join, equal:[eq(test.t6.b, test.t5.b)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t5.a)), not(isnull(test.t5.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t5 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t6.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t6 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t5), shuffle_join(t5) */ * from t4 join t5 join t6 where t4.a = t5.a and t5.b = t6.b;", + "Plan": [ + "TableReader 15593.77 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 15593.77 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 15593.77 mpp[tiflash] test.t4.a, test.t4.b, test.t5.a, test.t5.b, test.t6.a, test.t6.b", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t5.b, test.t6.b)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t6.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t6 pushed down filter:empty, keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 mpp[tiflash] inner join, equal:[eq(test.t5.a, test.t4.a)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t5.a, collate: binary]", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t5.a)), not(isnull(test.t5.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t5 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t4.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t4.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t4 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t6), broadcast_join(t4) */ * from t4 join t5 join t6 where t4.a = t5.a and t5.b = t6.b;", + "Plan": [ + "TableReader 15593.77 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 15593.77 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 15593.77 mpp[tiflash] test.t4.a, test.t4.b, test.t5.a, test.t5.b, test.t6.a, test.t6.b", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t5.a, test.t4.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t4.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t4 pushed down filter:empty, keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 mpp[tiflash] inner join, equal:[eq(test.t6.b, test.t5.b)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t5.a)), not(isnull(test.t5.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t5 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t6.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t6 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t5), broadcast_join(t5) */ * from t4 join t5 join t6 where t4.a = t5.a and t5.b = t6.b;", + "Plan": [ + "TableReader 15593.77 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 15593.77 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 15593.77 mpp[tiflash] test.t4.a, test.t4.b, test.t5.a, test.t5.b, test.t6.a, test.t6.b", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t5.b, test.t6.b)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t6.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t6 pushed down filter:empty, keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 mpp[tiflash] inner join, equal:[eq(test.t5.a, test.t4.a)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t5.a)), not(isnull(test.t5.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t5 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t4.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t4 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t3), hash_join(t1) */ * from t1 join t2 on t1.a = t2.a left join t3 on t2.b = t3.b;", + "Plan": [ + "Projection 15609.38 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15609.38 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12487.50 root left outer join, equal:[eq(test.t2.b, test.t3.b)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2), hash_join(t2) */ * from t1 join t2 on t1.a = t2.a left join t3 on t2.b = t3.b;", + "Plan": [ + "Projection 15609.38 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15609.38 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12487.50 root left outer join, equal:[eq(test.t2.b, test.t3.b)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t2.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t3), merge_join(t1) */ * from t1 right join t2 on t1.a = t2.a join t3 on t2.b = t3.b;", + "Plan": [ + "Projection 15609.38 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─MergeJoin 15609.38 root right outer join, left key:test.t1.a, right key:test.t2.a", + " ├─Projection(Build) 10000.00 root test.t1.a, test.t1.b", + " │ └─IndexLookUp 10000.00 root ", + " │ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " │ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─Sort(Probe) 12487.50 root test.t2.a", + " └─HashJoin 12487.50 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " │ └─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.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2), merge_join(t2) */ * from t1 right join t2 on t1.a = t2.a join t3 on t2.b = t3.b;", + "Plan": [ + "HashJoin 15609.38 root right outer join, equal:[eq(test.t1.a, test.t2.a)]", + "├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─MergeJoin(Probe) 12487.50 root inner join, left key:test.t2.b, right key:test.t3.b", + " ├─Projection(Build) 9990.00 root test.t3.a, test.t3.b", + " │ └─IndexLookUp 9990.00 root ", + " │ ├─IndexFullScan(Build) 9990.00 cop[tikv] table:t3, index:idx_b(b) keep order:true, stats:pseudo", + " │ └─TableRowIDScan(Probe) 9990.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─Projection(Probe) 9990.00 root test.t2.a, test.t2.b", + " └─IndexLookUp 9990.00 root ", + " ├─IndexFullScan(Build) 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, stats:pseudo", + " └─TableRowIDScan(Probe) 9990.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t3), inl_join(t1) */ * from t1 join t2 on t1.a = t2.a straight_join t3 on t2.b = t3.b;", + "Plan": [ + "HashJoin 15593.77 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "└─Projection(Probe) 12475.01 root test.t1.a, test.t1.b, test.t2.a, test.t2.b", + " └─IndexJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t2.a, inner key:test.t1.a, equal cond:eq(test.t2.a, test.t1.a)", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─IndexLookUp(Probe) 12475.01 root ", + " ├─IndexRangeScan(Build) 12475.01 cop[tikv] table:t1, index:idx_a(a) range: decided by [eq(test.t1.a, test.t2.a)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 12475.01 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]leading hint is inapplicable, check the join type or the join algorithm hint" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2), inl_join(t2) */ * from t1 join t2 on t1.a = t2.a straight_join t3 on t2.b = t3.b;", + "Plan": [ + "HashJoin 15593.77 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "└─Projection(Probe) 12475.01 root test.t1.a, test.t1.b, test.t2.a, test.t2.b", + " └─IndexJoin 12475.01 root inner join, inner:IndexLookUp, outer key:test.t1.a, inner key:test.t2.a, equal cond:eq(test.t1.a, test.t2.a)", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─IndexLookUp(Probe) 12475.01 root ", + " ├─Selection(Build) 12487.50 cop[tikv] not(isnull(test.t2.a))", + " │ └─IndexRangeScan 12500.00 cop[tikv] table:t2, index:idx_a(a) range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo", + " └─Selection(Probe) 12475.01 cop[tikv] not(isnull(test.t2.b))", + " └─TableRowIDScan 12487.50 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t3), hash_join_build(t1) */ * from t1 cross join t2 on t1.a = t2.a join t3 on t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ └─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.t3.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2), hash_join_probe(t2) */ * from t1 cross join t2 on t1.a = t2.a join t3 on t2.b = t3.b;", + "Plan": [ + "Projection 15593.77 root test.t1.a, test.t1.b, test.t2.a, test.t2.b, test.t3.a, test.t3.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9980.01 root data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select * from v", + "Plan": [ + "HashJoin 15609.38 root inner join, equal:[eq(test.t1.a, test.t.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:false, stats:pseudo", + "└─IndexJoin(Probe) 12487.50 root inner join, inner:IndexLookUp, outer key:test.t2.b, inner key:test.t1.b, equal cond:eq(test.t2.b, test.t1.b)", + " ├─IndexReader(Build) 9990.00 root index:IndexFullScan", + " │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:false, stats:pseudo", + " └─IndexLookUp(Probe) 12487.50 root ", + " ├─Selection(Build) 12487.50 cop[tikv] not(isnull(test.t1.b))", + " │ └─IndexRangeScan 12500.00 cop[tikv] table:t1, index:idx_b(b) range: decided by [eq(test.t1.b, test.t2.b)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 12487.50 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select * from v1", + "Plan": [ + "MergeJoin 15609.38 root inner join, left key:test.t1.a, right key:test.t.a", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + "└─Sort(Probe) 12487.50 root test.t1.a", + " └─HashJoin 12487.50 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + " ├─IndexReader(Build) 9990.00 root index:IndexFullScan", + " │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_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" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb, v2), leading(t2@qb), merge_join(t@qb) */ * from v2", + "Plan": [ + "MergeJoin 15609.38 root inner join, left key:test.t1.a, right key:test.t.a", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + "└─Sort(Probe) 12487.50 root test.t1.a", + " └─HashJoin 12487.50 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + " ├─IndexReader(Build) 9990.00 root index:IndexFullScan", + " │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_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" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb, v2), leading(t1@qb), inl_join(t1@qb) */ * from v2", + "Plan": [ + "HashJoin 15609.38 root inner join, equal:[eq(test.t1.a, test.t.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:false, stats:pseudo", + "└─IndexJoin(Probe) 12487.50 root inner join, inner:IndexLookUp, outer key:test.t2.b, inner key:test.t1.b, equal cond:eq(test.t2.b, test.t1.b)", + " ├─IndexReader(Build) 9990.00 root index:IndexFullScan", + " │ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:false, stats:pseudo", + " └─IndexLookUp(Probe) 12487.50 root ", + " ├─Selection(Build) 12487.50 cop[tikv] not(isnull(test.t1.b))", + " │ └─IndexRangeScan 12500.00 cop[tikv] table:t1, index:idx_b(b) range: decided by [eq(test.t1.b, test.t2.b)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 12487.50 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain with tt as (select /*+ leading(t3), merge_join(t1) */ t1.a from t1 join t2 join t3 where t1.a = t2.a and t2.b=t3.b) select * from tt t1 join tt t2 on t1.a=t2.a", + "Plan": [ + "HashJoin_113 24316.55 root inner join, equal:[eq(test.t1.a, test.t1.a)]", + "├─Selection_117(Build) 12475.01 root not(isnull(test.t1.a))", + "│ └─CTEFullScan_118 15593.77 root CTE:tt AS t2 data:CTE_0", + "└─Selection_115(Probe) 12475.01 root not(isnull(test.t1.a))", + " └─CTEFullScan_116 15593.77 root CTE:tt AS t1 data:CTE_0", + "CTE_0 15593.77 root Non-Recursive CTE", + "└─MergeJoin_22(Seed Part) 15593.77 root inner join, left key:test.t2.a, right key:test.t1.a", + " ├─IndexReader_110(Build) 10000.00 root index:IndexFullScan_109", + " │ └─IndexFullScan_109 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " └─Sort_108(Probe) 12475.01 root test.t2.a", + " └─HashJoin_81 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─IndexReader_91(Build) 9990.00 root index:IndexFullScan_90", + " │ └─IndexFullScan_90 9990.00 cop[tikv] table:t3, index:idx_b(b) keep order:false, stats:pseudo", + " └─TableReader_96(Probe) 9980.01 root data:Selection_95", + " └─Selection_95 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " └─TableFullScan_94 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain with tt as (select /*+ leading(t2), inl_join(t2) */ t1.a from t1 join t2 join t3 where t1.a = t2.a and t2.b=t3.b) select * from tt t1 join tt t2 on t1.a=t2.a", + "Plan": [ + "HashJoin_112 24316.55 root inner join, equal:[eq(test.t1.a, test.t1.a)]", + "├─Selection_116(Build) 12475.01 root not(isnull(test.t1.a))", + "│ └─CTEFullScan_117 15593.77 root CTE:tt AS t2 data:CTE_0", + "└─Selection_114(Probe) 12475.01 root not(isnull(test.t1.a))", + " └─CTEFullScan_115 15593.77 root CTE:tt AS t1 data:CTE_0", + "CTE_0 15593.77 root Non-Recursive CTE", + "└─HashJoin_32(Seed Part) 15593.77 root inner join, equal:[eq(test.t2.a, test.t1.a)]", + " ├─IndexReader_109(Build) 10000.00 root index:IndexFullScan_108", + " │ └─IndexFullScan_108 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + " └─IndexJoin_95(Probe) 12475.01 root inner join, inner:IndexLookUp_94, outer key:test.t3.b, inner key:test.t2.b, equal cond:eq(test.t3.b, test.t2.b)", + " ├─IndexReader_74(Build) 9990.00 root index:IndexFullScan_73", + " │ └─IndexFullScan_73 9990.00 cop[tikv] table:t3, index:idx_b(b) keep order:false, stats:pseudo", + " └─IndexLookUp_94(Probe) 12475.01 root ", + " ├─Selection_92(Build) 12487.50 cop[tikv] not(isnull(test.t2.b))", + " │ └─IndexRangeScan_90 12500.00 cop[tikv] table:t2, index:idx_b(b) range: decided by [eq(test.t2.b, test.t3.b)], keep order:false, stats:pseudo", + " └─Selection_93(Probe) 12475.01 cop[tikv] not(isnull(test.t2.a))", + " └─TableRowIDScan_91 12487.50 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain with tt as (select /*+ merge(), leading(t3), inl_join(t1) */ t1.a from t1 join t2 join t3 where t1.a = t2.a and t2.b=t3.b) select * from tt t1 join tt t2 on t1.a=t2.a", + "Plan": [ + "HashJoin_48 30395.69 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + "├─IndexReader_169(Build) 9990.00 root index:IndexFullScan_168", + "│ └─IndexFullScan_168 9990.00 cop[tikv] table:t3, index:idx_b(b) keep order:false, stats:pseudo", + "└─HashJoin_68(Probe) 24316.55 root inner join, equal:[eq(test.t1.a, test.t2.a)]", + " ├─TableReader_159(Build) 9980.01 root data:Selection_158", + " │ └─Selection_158 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ └─TableFullScan_157 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─IndexJoin_150(Probe) 19492.21 root inner join, inner:IndexReader_149, outer key:test.t1.a, inner key:test.t1.a, equal cond:eq(test.t1.a, test.t1.a)", + " ├─IndexJoin_84(Build) 15593.77 root inner join, inner:IndexReader_83, outer key:test.t2.a, inner key:test.t1.a, equal cond:eq(test.t2.a, test.t1.a)", + " │ ├─HashJoin_119(Build) 12475.01 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + " │ │ ├─IndexReader_140(Build) 9990.00 root index:IndexFullScan_139", + " │ │ │ └─IndexFullScan_139 9990.00 cop[tikv] table:t3, index:idx_b(b) keep order:false, stats:pseudo", + " │ │ └─TableReader_130(Probe) 9980.01 root data:Selection_129", + " │ │ └─Selection_129 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " │ │ └─TableFullScan_128 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " │ └─IndexReader_83(Probe) 15593.77 root index:IndexRangeScan_82", + " │ └─IndexRangeScan_82 15593.77 cop[tikv] table:t1, index:idx_a(a) range: decided by [eq(test.t1.a, test.t2.a)], keep order:false, stats:pseudo", + " └─IndexReader_149(Probe) 19492.21 root index:IndexRangeScan_148", + " └─IndexRangeScan_148 19492.21 cop[tikv] table:t1, index:idx_a(a) range: decided by [eq(test.t1.a, test.t1.a)], keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid", + "[planner:1815]There are no matching table names for (t1) in optimizer hint /*+ INL_JOIN(t1, t1) */ or /*+ TIDB_INLJ(t1, t1) */. Maybe you can use the table alias name", + "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid", + "[planner:1815]There are no matching table names for (t1, t1) in optimizer hint /*+ INL_JOIN(t1, t1, t1) */ or /*+ TIDB_INLJ(t1, t1, t1) */. Maybe you can use the table alias name" + ] + }, + { + "SQL": "explain with tt as (select /*+ leading(t2), merge_join(t2), merge() */ t1.a from t1 join t2 join t3 where t1.a = t2.a and t2.b=t3.b) select * from tt t1 join tt t2 on t1.a=t2.a", + "Plan": [ + "HashJoin_48 30395.69 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + "├─IndexReader_145(Build) 9990.00 root index:IndexFullScan_144", + "│ └─IndexFullScan_144 9990.00 cop[tikv] table:t3, index:idx_b(b) keep order:false, stats:pseudo", + "└─MergeJoin_142(Probe) 24316.55 root inner join, left key:test.t1.a, right key:test.t2.a", + " ├─Projection_92(Build) 9980.01 root test.t2.a, test.t2.b", + " │ └─IndexLookUp_91 9980.01 root ", + " │ ├─IndexFullScan_88(Build) 9990.00 cop[tikv] table:t2, index:idx_a(a) keep order:true, stats:pseudo", + " │ └─Selection_90(Probe) 9980.01 cop[tikv] not(isnull(test.t2.b))", + " │ └─TableRowIDScan_89 9990.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─MergeJoin_53(Probe) 19492.21 root inner join, left key:test.t1.a, right key:test.t1.a", + " ├─IndexReader_87(Build) 10000.00 root index:IndexFullScan_86", + " │ └─IndexFullScan_86 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " └─MergeJoin_54(Probe) 15593.77 root inner join, left key:test.t2.a, right key:test.t1.a", + " ├─IndexReader_85(Build) 10000.00 root index:IndexFullScan_84", + " │ └─IndexFullScan_84 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " └─Sort_75(Probe) 12475.01 root test.t2.a", + " └─MergeJoin_66 12475.01 root inner join, left key:test.t2.b, right key:test.t3.b", + " ├─IndexReader_74(Build) 9990.00 root index:IndexFullScan_73", + " │ └─IndexFullScan_73 9990.00 cop[tikv] table:t3, index:idx_b(b) keep order:true, stats:pseudo", + " └─Projection_72(Probe) 9980.01 root test.t2.a, test.t2.b", + " └─IndexLookUp_71 9980.01 root ", + " ├─IndexFullScan_68(Build) 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:true, stats:pseudo", + " └─Selection_70(Probe) 9980.01 cop[tikv] not(isnull(test.t2.a))", + " └─TableRowIDScan_69 9990.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid", + "[planner:1815]There are no matching table names for (t2) in optimizer hint /*+ MERGE_JOIN(t2, t2) */ or /*+ TIDB_SMJ(t2, t2) */. Maybe you can use the table alias name", + "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid", + "[planner:1815]There are no matching table names for (t2, t2) in optimizer hint /*+ MERGE_JOIN(t2, t2, t2) */ or /*+ TIDB_SMJ(t2, t2, t2) */. Maybe you can use the table alias name" + ] + }, + { + "SQL": "explain format = 'brief' SELECT /*+ leading(t2@sel_2), merge_join(t) */ * FROM t join t1 on t.a = t1.a WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.b = t1.b);", + "Plan": [ + "HashJoin 9990.00 root semi join, equal:[eq(test.t1.b, test.t2.b)]", + "├─IndexReader(Build) 9990.00 root index:IndexFullScan", + "│ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:false, stats:pseudo", + "└─Projection(Probe) 12487.50 root test.t.a, test.t.b, test.t1.a, test.t1.b", + " └─MergeJoin 12487.50 root inner join, left key:test.t1.a, right key:test.t.a", + " ├─Projection(Build) 10000.00 root test.t.a, test.t.b", + " │ └─IndexLookUp 10000.00 root ", + " │ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + " │ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 9990.00 root test.t1.a, test.t1.b", + " └─IndexLookUp 9990.00 root ", + " ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " └─Selection(Probe) 9990.00 cop[tikv] not(isnull(test.t1.b))", + " └─TableRowIDScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]leading hint is inapplicable, check the join type or the join algorithm hint" + ] + }, + { + "SQL": "explain format = 'brief' SELECT /*+ leading(t1), inl_join(t1) */ * FROM t join t1 on t.a = t1.a WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.b = t1.b);", + "Plan": [ + "HashJoin 9990.00 root semi join, equal:[eq(test.t1.b, test.t2.b)]", + "├─IndexReader(Build) 9990.00 root index:IndexFullScan", + "│ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:idx_b(b) keep order:false, stats:pseudo", + "└─Projection(Probe) 12487.50 root test.t.a, test.t.b, test.t1.a, test.t1.b", + " └─IndexJoin 12487.50 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.t1.a, equal cond:eq(test.t.a, test.t1.a)", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + " └─IndexLookUp(Probe) 12487.50 root ", + " ├─IndexRangeScan(Build) 12500.00 cop[tikv] table:t1, index:idx_a(a) range: decided by [eq(test.t1.a, test.t.a)], keep order:false, stats:pseudo", + " └─Selection(Probe) 12487.50 cop[tikv] not(isnull(test.t1.b))", + " └─TableRowIDScan 12500.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' SELECT /*+ leading(t2@sel_2), merge_join(t) */ * FROM t join t1 on t.a = t1.a WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.b = t1.b);", + "Plan": [ + "Projection 12487.50 root test.t.a, test.t.b, test.t1.a, test.t1.b", + "└─MergeJoin 12487.50 root inner join, left key:test.t1.a, right key:test.t.a", + " ├─Projection(Build) 10000.00 root test.t.a, test.t.b", + " │ └─IndexLookUp 10000.00 root ", + " │ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + " │ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + " └─Sort(Probe) 9990.00 root test.t1.a", + " └─HashJoin 9990.00 root inner join, equal:[eq(test.t2.b, test.t1.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:idx_b(b) keep order:true, 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" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' SELECT /*+ leading(t1), inl_join(t1) */ * FROM t join t1 on t.a = t1.a WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t2 WHERE t2.b = t1.b);", + "Plan": [ + "Projection 12487.50 root test.t.a, test.t.b, test.t1.a, test.t1.b", + "└─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, 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:idx_b(b) keep order:true, stats:pseudo", + " └─IndexJoin(Probe) 12487.50 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.t1.a, equal cond:eq(test.t.a, test.t1.a)", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + " └─IndexLookUp(Probe) 12487.50 root ", + " ├─IndexRangeScan(Build) 12500.00 cop[tikv] table:t1, index:idx_a(a) range: decided by [eq(test.t1.a, test.t.a)], keep order:false, stats:pseudo", + " └─Selection(Probe) 12487.50 cop[tikv] not(isnull(test.t1.b))", + " └─TableRowIDScan 12500.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t2@sel_2) merge_join(t) */ * from t join t1 on t.a = t1.a where t1.a < (select sum(t2.a) from t2 where t2.b = t1.b);", + "Plan": [ + "Projection 12487.50 root test.t.a, test.t.b, test.t1.a, test.t1.b", + "└─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)], other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#10)", + " ├─HashAgg(Build) 7992.00 root group by:test.t2.b, funcs:sum(Column#24)->Column#10, funcs:firstrow(test.t2.b)->test.t2.b", + " │ └─TableReader 7992.00 root data:HashAgg", + " │ └─HashAgg 7992.00 cop[tikv] group by:test.t2.b, funcs:sum(test.t2.a)->Column#24", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─MergeJoin(Probe) 12487.50 root inner join, left key:test.t1.a, right key:test.t.a", + " ├─Projection(Build) 10000.00 root test.t.a, test.t.b", + " │ └─IndexLookUp 10000.00 root ", + " │ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + " │ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + " └─Projection(Probe) 9990.00 root test.t1.a, test.t1.b", + " └─IndexLookUp 9990.00 root ", + " ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " └─Selection(Probe) 9990.00 cop[tikv] not(isnull(test.t1.b))", + " └─TableRowIDScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]There are no matching table names for (t2) in optimizer hint /*+ LEADING(t2) */. Maybe you can use the table alias name" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t1), inl_join(t1) */ * from t join t1 on t.a = t1.a where t1.a < (select sum(t2.a) from t2 where t2.b = t1.b);", + "Plan": [ + "Projection 12487.50 root test.t.a, test.t.b, test.t1.a, test.t1.b", + "└─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)], other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#10)", + " ├─HashAgg(Build) 7992.00 root group by:test.t2.b, funcs:sum(Column#28)->Column#10, funcs:firstrow(test.t2.b)->test.t2.b", + " │ └─TableReader 7992.00 root data:HashAgg", + " │ └─HashAgg 7992.00 cop[tikv] group by:test.t2.b, funcs:sum(test.t2.a)->Column#28", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + " └─IndexJoin(Probe) 12487.50 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.t1.a, equal cond:eq(test.t.a, test.t1.a)", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + " └─IndexLookUp(Probe) 12487.50 root ", + " ├─IndexRangeScan(Build) 12500.00 cop[tikv] table:t1, index:idx_a(a) range: decided by [eq(test.t1.a, test.t.a)], keep order:false, stats:pseudo", + " └─Selection(Probe) 12487.50 cop[tikv] not(isnull(test.t1.b))", + " └─TableRowIDScan 12500.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+leading(t2@sel_2) merge_join(t) */ * from t join t1 on t.a = t1.a where t1.a < (select /*+ NO_DECORRELATE() */ sum(t2.a) from t2 where t2.b = t1.b);", + "Plan": [ + "Projection 12500.00 root test.t.a, test.t.b, test.t1.a, test.t1.b", + "└─Apply 12500.00 root CARTESIAN inner join, other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#10)", + " ├─MergeJoin(Build) 12500.00 root inner join, left key:test.t.a, right key:test.t1.a", + " │ ├─Projection(Build) 10000.00 root test.t1.a, test.t1.b", + " │ │ └─IndexLookUp 10000.00 root ", + " │ │ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " │ │ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " │ └─Projection(Probe) 10000.00 root test.t.a, test.t.b", + " │ └─IndexLookUp 10000.00 root ", + " │ ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + " │ └─TableRowIDScan(Probe) 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + " └─MaxOneRow(Probe) 12500.00 root ", + " └─StreamAgg 12500.00 root funcs:sum(Column#25)->Column#10", + " └─Projection 125000.00 root cast(test.t2.a, decimal(10,0) BINARY)->Column#25", + " └─IndexLookUp 125000.00 root ", + " ├─IndexRangeScan(Build) 125000.00 cop[tikv] table:t2, index:idx_b(b) range: decided by [eq(test.t2.b, test.t1.b)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 125000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]There are no matching table names for (t2) in optimizer hint /*+ LEADING(t2) */. Maybe you can use the table alias name" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t1), inl_join(t1) */ * from t join t1 on t.a = t1.a where t1.a < (select /*+ NO_DECORRELATE() */ sum(t2.a) from t2 where t2.b = t1.b);", + "Plan": [ + "Projection 12500.00 root test.t.a, test.t.b, test.t1.a, test.t1.b", + "└─Apply 12500.00 root CARTESIAN inner join, other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#10)", + " ├─Projection(Build) 12500.00 root test.t.a, test.t.b, test.t1.a, test.t1.b", + " │ └─IndexJoin 12500.00 root inner join, inner:IndexLookUp, outer key:test.t.a, inner key:test.t1.a, equal cond:eq(test.t.a, test.t1.a)", + " │ ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + " │ └─IndexLookUp(Probe) 12500.00 root ", + " │ ├─IndexRangeScan(Build) 12500.00 cop[tikv] table:t1, index:idx_a(a) range: decided by [eq(test.t1.a, test.t.a)], keep order:false, stats:pseudo", + " │ └─TableRowIDScan(Probe) 12500.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + " └─MaxOneRow(Probe) 12500.00 root ", + " └─StreamAgg 12500.00 root funcs:sum(Column#23)->Column#10", + " └─Projection 125000.00 root cast(test.t2.a, decimal(10,0) BINARY)->Column#23", + " └─IndexLookUp 125000.00 root ", + " ├─IndexRangeScan(Build) 125000.00 cop[tikv] table:t2, index:idx_b(b) range: decided by [eq(test.t2.b, test.t1.b)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 125000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t9), hash_join(t7) */ * from t7 join t8 join t9 where t7.a = t8.a and t8.b = t9.b;", + "Plan": [ + "Projection 15593.77 root test.t7.a, test.t7.b, test.t8.a, test.t8.b, test.t9.a, test.t9.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t8.a, test.t7.a)]", + " ├─TableReader(Build) 9990.00 root partition:all data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t7.a))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t7 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t9.b, test.t8.b)]", + " ├─TableReader(Build) 9980.01 root partition:all data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t8.a)), not(isnull(test.t8.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t8 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root partition:all data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t9.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t9 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ leading(t8), hash_join(t8) */ * from t7 join t8 join t9 where t7.a = t8.a and t8.b = t9.b;", + "Plan": [ + "Projection 15593.77 root test.t7.a, test.t7.b, test.t8.a, test.t8.b, test.t9.a, test.t9.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t8.b, test.t9.b)]", + " ├─TableReader(Build) 9990.00 root partition:all data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t9.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t9 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t8.a, test.t7.a)]", + " ├─TableReader(Build) 9980.01 root partition:all data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t8.a)), not(isnull(test.t8.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t8 keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root partition:all data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t7.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t7 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ read_from_storage(tikv[t4, t6]), leading(t6), hash_join_build(t4) */ * from t4 join t5 join t6 where t4.a = t5.a and t5.b = t6.b;", + "Plan": [ + "Projection 15593.77 root test.t4.a, test.t4.b, test.t5.a, test.t5.b, test.t6.a, test.t6.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t5.a, test.t4.a)]", + " ├─TableReader(Build) 9990.00 root data:Selection", + " │ └─Selection 9990.00 cop[tikv] not(isnull(test.t4.a))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t6.b, test.t5.b)]", + " ├─TableReader(Build) 9980.01 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: PassThrough", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t5.a)), not(isnull(test.t5.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t5 pushed down filter:empty, keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t6.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t6 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ read_from_storage(tikv[t5]), leading(t5), hash_join_probe(t5) */ * from t4 join t5 join t6 where t4.a = t5.a and t5.b = t6.b;", + "Plan": [ + "Projection 15593.77 root test.t4.a, test.t4.b, test.t5.a, test.t5.b, test.t6.a, test.t6.b", + "└─HashJoin 15593.77 root inner join, equal:[eq(test.t5.b, test.t6.b)]", + " ├─TableReader(Build) 9990.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t6.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t6 pushed down filter:empty, keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t5.a, test.t4.a)]", + " ├─TableReader(Build) 9990.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t4.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t4 pushed down filter:empty, keep order:false, stats:pseudo", + " └─TableReader(Probe) 9980.01 root data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t5.a)), not(isnull(test.t5.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ read_from_storage(tiflash[t4, t6]), leading(t6), hash_join_build(t4) */ * from t4 join t5 join t6 where t4.a = t5.a and t5.b = t6.b;", + "Plan": [ + "TableReader 15593.77 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 15593.77 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 15593.77 mpp[tiflash] test.t4.a, test.t4.b, test.t5.a, test.t5.b, test.t6.a, test.t6.b", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t5.a, test.t4.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t4.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t4 pushed down filter:empty, keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 mpp[tiflash] inner join, equal:[eq(test.t6.b, test.t5.b)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t5.a)), not(isnull(test.t5.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t5 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t6.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t6 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ read_from_storage(tiflash[t5]), leading(t5), hash_join_probe(t5) */ * from t4 join t5 join t6 where t4.a = t5.a and t5.b = t6.b;", + "Plan": [ + "TableReader 15593.77 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 15593.77 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 15593.77 mpp[tiflash] test.t4.a, test.t4.b, test.t5.a, test.t5.b, test.t6.a, test.t6.b", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t5.b, test.t6.b)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t6.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t6 pushed down filter:empty, keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 mpp[tiflash] inner join, equal:[eq(test.t5.a, test.t4.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t4.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t4 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9980.01 mpp[tiflash] not(isnull(test.t5.a)), not(isnull(test.t5.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t5 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, + { + "Name": "TestReadFromStorageHintAndIsolationRead", + "Cases": [ + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tikv[t], tiflash[t]) */ avg(a) from t", + "Plan": [ + "HashAgg 1.00 root funcs:avg(Column#5, Column#6)->Column#4", + "└─IndexReader 1.00 root index:HashAgg", + " └─HashAgg 1.00 cop[tikv] funcs:count(test.t.a)->Column#5, funcs:sum(test.t.a)->Column#6", + " └─IndexFullScan 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Storage hints are conflict, you can only specify one storage type of table test.t" + ] + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tikv[t]) */ avg(a) from t", + "Plan": [ + "HashAgg 1.00 root funcs:avg(Column#5, Column#6)->Column#4", + "└─IndexReader 1.00 root index:HashAgg", + " └─HashAgg 1.00 cop[tikv] funcs:count(test.t.a)->Column#5, funcs:sum(test.t.a)->Column#6", + " └─IndexFullScan 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "desc format = 'brief' select /*+ read_from_storage(tiflash[t]) */ avg(a) from t", + "Plan": [ + "HashAgg 1.00 root funcs:avg(Column#5, Column#6)->Column#4", + "└─IndexReader 1.00 root index:HashAgg", + " └─HashAgg 1.00 cop[tikv] funcs:count(test.t.a)->Column#5, funcs:sum(test.t.a)->Column#6", + " └─IndexFullScan 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]No available path for table test.t with the store type tiflash of the hint /*+ read_from_storage */, please check the status of the table replica and variable value of tidb_isolation_read_engines(map[0:{}])" + ] + } + ] + }, + { + "Name": "TestIsolationReadTiFlashUseIndexHint", + "Cases": [ + { + "SQL": "explain format = 'brief' select * from t", + "Plan": [ + "TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select * from t use index();", + "Plan": [ + "TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ use_index(t, idx)*/ * from t", + "Plan": [ + "TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "TiDB doesn't support index in the isolation read engines(value: 'tiflash')" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ use_index(t)*/ * from t", + "Plan": [ + "TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, + { + "Name": "TestHints", + "Cases": [ + { + "SQL": "select * from t1, t2, t3 union all select /*+ leading(t3, t2) */ * from t1, t2, t3 union all select * from t1, t2, t3", + "Plan": [ + "Union 3000000000000.00 root ", + "├─HashJoin 1000000000000.00 root CARTESIAN inner join", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 100000000.00 root CARTESIAN inner join", + "│ ├─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", + "├─Projection 1000000000000.00 root test.t1.a->Column#19, test.t2.a->Column#20, test.t3.a->Column#21", + "│ └─HashJoin 1000000000000.00 root CARTESIAN inner join", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 100000000.00 root CARTESIAN inner join", + "│ ├─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:t3 keep order:false, stats:pseudo", + "└─HashJoin 1000000000000.00 root CARTESIAN inner join", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─HashJoin(Probe) 100000000.00 root CARTESIAN inner join", + " ├─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" + ], + "Warn": [ + "Warning 1815 leading hint is inapplicable, check if the leading hint table has join conditions with other tables" + ] + } + ] + } +] diff --git a/pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json b/pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json new file mode 100644 index 0000000000000..05c75cbb2b649 --- /dev/null +++ b/pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json @@ -0,0 +1,3750 @@ +[ + { + "Name": "TestMPPHints", + "Cases": [ + { + "SQL": "select /*+ MPP_1PHASE_AGG() */ a, sum(b) from t group by a, c", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#10, Column#11, funcs:sum(Column#8)->Column#5, funcs:firstrow(Column#9)->test.t.a", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#8, test.t.a->Column#9, test.t.a->Column#10, test.t.c->Column#11", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ MPP_2PHASE_AGG() */ a, sum(b) from t group by a, c", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.a, test.t.c, funcs:sum(Column#10)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, Column#14, funcs:sum(Column#12)->Column#10", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#12, test.t.a->Column#13, test.t.c->Column#14", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ shuffle_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ broadcast_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_1PHASE_AGG() */ a, sum(b) from t group by a, c", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#8, Column#9, funcs:sum(Column#6)->Column#5, funcs:firstrow(Column#7)->test.t.a", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#6, test.t.a->Column#7, test.t.a->Column#8, test.t.c->Column#9", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_2PHASE_AGG() */ a, sum(b) from t group by a, c", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.a, test.t.c, funcs:sum(Column#8)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#11, Column#12, funcs:sum(Column#10)->Column#8", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#10, test.t.a->Column#11, test.t.c->Column#12", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_build(t1) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_build(t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_build(t1) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_probe(t1) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_probe(t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_probe(t1) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), merge_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]The MPP join hints are in conflict, and you can only specify join method hints that are currently supported by MPP mode now" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), merge_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]The MPP join hints are in conflict, and you can only specify join method hints that are currently supported by MPP mode now" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), INL_JOIN(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]The MPP join hints are in conflict, and you can only specify join method hints that are currently supported by MPP mode now" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), INL_JOIN(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]The MPP join hints are in conflict, and you can only specify join method hints that are currently supported by MPP mode now" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_1PHASE_AGG(), hash_agg() */ a, sum(b) from t group by a, c", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#8, Column#9, funcs:sum(Column#6)->Column#5, funcs:firstrow(Column#7)->test.t.a", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#6, test.t.a->Column#7, test.t.a->Column#8, test.t.c->Column#9", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_2PHASE_AGG(), stream_agg() */ a, sum(b) from t group by a, c", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.a, test.t.c, funcs:sum(Column#6)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#10, Column#9, funcs:sum(Column#8)->Column#6", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#8, test.t.a->Column#9, test.t.c->Column#10", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_1PHASE_AGG(), use_index(t, idx_a) */ a, sum(b) from t where a > 1 group by a, c", + "Plan": [ + "Projection 2666.67 root test.t.a, Column#5", + "└─HashAgg 2666.67 root group by:test.t.a, test.t.c, funcs:sum(Column#7)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─IndexLookUp 2666.67 root ", + " ├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo", + " └─HashAgg(Probe) 2666.67 cop[tikv] group by:test.t.a, test.t.c, funcs:sum(test.t.b)->Column#7", + " └─TableRowIDScan 3333.33 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]No available path for table test.t with the store type tiflash of the hint /*+ read_from_storage */, please check the status of the table replica and variable value of tidb_isolation_read_engines(map[0:{} 1:{} 2:{}])", + "[planner:1815]The agg can not push down to the MPP side, the MPP_1PHASE_AGG() hint is invalid" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_1PHASE_AGG(), ignore_index(t, idx_a) */ a, sum(b) from t where a > 1 group by a, c", + "Plan": [ + "TableReader 2666.67 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 2666.67 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 2666.67 mpp[tiflash] test.t.a, Column#5", + " └─Projection 2666.67 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 2666.67 mpp[tiflash] group by:Column#8, Column#9, funcs:sum(Column#6)->Column#5, funcs:firstrow(Column#7)->test.t.a", + " └─Projection 3333.33 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#6, test.t.a->Column#7, test.t.a->Column#8, test.t.c->Column#9", + " └─ExchangeReceiver 3333.33 mpp[tiflash] ", + " └─ExchangeSender 3333.33 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─Selection 3333.33 mpp[tiflash] gt(test.t.a, 1)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_2PHASE_AGG(), force_index(t, idx_b) */ a, sum(b) from t where b < 2 group by a, c", + "Plan": [ + "Projection 2658.67 root test.t.a, Column#5", + "└─HashAgg 2658.67 root group by:test.t.a, test.t.c, funcs:sum(Column#7)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─IndexLookUp 2658.67 root ", + " ├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t, index:idx_b(b) range:[-inf,2), keep order:false, stats:pseudo", + " └─HashAgg(Probe) 2658.67 cop[tikv] group by:test.t.a, test.t.c, funcs:sum(test.t.b)->Column#7", + " └─TableRowIDScan 3323.33 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]No available path for table test.t with the store type tiflash of the hint /*+ read_from_storage */, please check the status of the table replica and variable value of tidb_isolation_read_engines(map[0:{} 1:{} 2:{}])", + "[planner:1815]The agg can not push down to the MPP side, the MPP_2PHASE_AGG() hint is invalid" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t]), MPP_2PHASE_AGG(), index_merge(t, idx_b, idx_a) */ a, sum(b) from t where b < 2 or a > 2 group by a, c", + "Plan": [ + "TableReader 4439.11 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 4439.11 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 4439.11 mpp[tiflash] test.t.a, Column#5", + " └─Projection 4439.11 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 4439.11 mpp[tiflash] group by:test.t.a, test.t.c, funcs:sum(Column#14)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─ExchangeReceiver 4439.11 mpp[tiflash] ", + " └─ExchangeSender 4439.11 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─HashAgg 4439.11 mpp[tiflash] group by:Column#17, Column#18, funcs:sum(Column#16)->Column#14", + " └─Projection 5548.89 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#16, test.t.a->Column#17, test.t.c->Column#18", + " └─Selection 5548.89 mpp[tiflash] or(lt(test.t.b, 2), gt(test.t.a, 2))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": [ + "[parser:8061]Optimizer hint index_merge is not supported by TiDB and is ignored" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2, t3]), shuffle_join(t1, t2, t3), straight_join() */ * from t t1, t t2, t t3 where t1.a=t2.a and t2.b=t3.b", + "Plan": [ + "TableReader 15593.77 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 15593.77 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t3 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 12475.01 mpp[tiflash] ", + " └─ExchangeSender 12475.01 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " └─HashJoin 12475.01 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.a)), not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2, t3]), shuffle_join(t1, t2, t3), leading(t3, t1) */ * from t t1, t t2, t t3 where t1.a=t2.a and t2.b=t3.b", + "Plan": [ + "TableReader 124625374.88 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 124625374.88 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 124625374.88 mpp[tiflash] test.t.a, test.t.b, test.t.c, test.t.a, test.t.b, test.t.c, test.t.a, test.t.b, test.t.c", + " └─HashJoin 124625374.88 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a) eq(test.t.b, test.t.b)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.b, collate: binary]", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.a)), not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 99800100.00 mpp[tiflash] ", + " └─ExchangeSender 99800100.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.b, collate: binary]", + " └─HashJoin 99800100.00 mpp[tiflash] CARTESIAN inner join", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t3 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2, t3]), broadcast_join(t1, t2, t3), straight_join() */ * from t t2, t t1, t t3 where t1.a=t2.a and t2.b=t3.b", + "Plan": [ + "TableReader 15593.77 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 15593.77 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t3 pushed down filter:empty, keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.a)), not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2, t3]), broadcast_join(t1, t2, t3), leading(t2, t3) */ * from t t1, t t2, t t3 where t1.a=t2.a and t2.b=t3.b", + "Plan": [ + "TableReader 15593.77 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 15593.77 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 15593.77 mpp[tiflash] test.t.a, test.t.b, test.t.c, test.t.a, test.t.b, test.t.c, test.t.a, test.t.b, test.t.c", + " └─HashJoin 15593.77 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)]", + " ├─ExchangeReceiver(Build) 9980.01 mpp[tiflash] ", + " │ └─ExchangeSender 9980.01 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9980.01 mpp[tiflash] not(isnull(test.t.a)), not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t3 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ qb_name(qb, v), MPP_1PHASE_AGG(@qb) */ * from v", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#10, Column#11, funcs:sum(Column#8)->Column#5, funcs:firstrow(Column#9)->test.t.a", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#8, test.t.a->Column#9, test.t.a->Column#10, test.t.c->Column#11", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ qb_name(qb, v), MPP_2PHASE_AGG(@qb) */ * from v", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.a, test.t.c, funcs:sum(Column#10)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, Column#14, funcs:sum(Column#12)->Column#10", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#12, test.t.a->Column#13, test.t.c->Column#14", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ qb_name(qb, v1), shuffle_join(t1@qb, t2@qb) */ * from v1", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12487.50 mpp[tiflash] test.t.a", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ qb_name(qb, v1), broadcast_join(t1@qb, t2@qb) */ * from v1", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12487.50 mpp[tiflash] test.t.a", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "SELECT /*+ shuffle_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t t1 WHERE t1.b = t.b);", + "Plan": [ + "TableReader 9990.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 9990.00 mpp[tiflash] test.t.a, test.t.b, test.t.c", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)]", + " ├─Projection(Build) 7992.00 mpp[tiflash] test.t.b", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.b, funcs:firstrow(test.t.b)->test.t.b", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.b, ", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "SELECT /*+ broadcast_join(t) */ * FROM t WHERE EXISTS (SELECT /*+ SEMI_JOIN_REWRITE() */ 1 FROM t t1 WHERE t1.b = t.b);", + "Plan": [ + "TableReader 9990.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 9990.00 mpp[tiflash] test.t.a, test.t.b, test.t.c", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)]", + " ├─ExchangeReceiver(Build) 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 7992.00 mpp[tiflash] test.t.b", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.b, funcs:firstrow(test.t.b)->test.t.b", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.b, ", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select * from t t1 where t1.a < (select /*+ MPP_1PHASE_AGG() */ sum(t2.a) from t t2 where t2.b = t1.b);", + "Plan": [ + "TableReader 9990.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 9990.00 mpp[tiflash] test.t.a, test.t.b, test.t.c", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)], other cond:lt(cast(test.t.a, decimal(10,0) BINARY), Column#9)", + " ├─ExchangeReceiver(Build) 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 7992.00 mpp[tiflash] Column#9, test.t.b", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:Column#26, funcs:sum(Column#24)->Column#9, funcs:firstrow(Column#25)->test.t.b", + " │ └─Projection 9990.00 mpp[tiflash] cast(test.t.a, decimal(10,0) BINARY)->Column#24, test.t.b->Column#25, test.t.b->Column#26", + " │ └─ExchangeReceiver 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select * from t t1 where t1.a < (select /*+ MPP_2PHASE_AGG() */ sum(t2.a) from t t2 where t2.b = t1.b);", + "Plan": [ + "TableReader 9990.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 9990.00 mpp[tiflash] test.t.a, test.t.b, test.t.c", + " └─HashJoin 9990.00 mpp[tiflash] inner join, equal:[eq(test.t.b, test.t.b)], other cond:lt(cast(test.t.a, decimal(10,0) BINARY), Column#9)", + " ├─ExchangeReceiver(Build) 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 7992.00 mpp[tiflash] Column#9, test.t.b", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:test.t.b, funcs:sum(Column#13)->Column#9, funcs:firstrow(test.t.b)->test.t.b", + " │ └─ExchangeReceiver 7992.00 mpp[tiflash] ", + " │ └─ExchangeSender 7992.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " │ └─HashAgg 7992.00 mpp[tiflash] group by:Column#29, funcs:sum(Column#28)->Column#13", + " │ └─Projection 9990.00 mpp[tiflash] cast(test.t.a, decimal(10,0) BINARY)->Column#28, test.t.b->Column#29", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.b))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "WITH CTE AS (SELECT /*+ MPP_1PHASE_AGG() */ count(*) as a, b FROM t WHERE t.a < 60 group by b) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "HashAgg 3403.09 root group by:Column#10, Column#11, funcs:firstrow(Column#10)->Column#10, funcs:firstrow(Column#11)->Column#11", + "└─Union 3403.09 root ", + " ├─Selection 1701.55 root lt(Column#6, 18)", + " │ └─CTEFullScan 2126.93 root CTE:cte data:CTE_0", + " └─Selection 1701.55 root gt(test.t.b, 1)", + " └─CTEFullScan 2126.93 root CTE:cte data:CTE_0", + "CTE_0 2126.93 root Non-Recursive CTE", + "└─TableReader(Seed Part) 2126.93 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 2126.93 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection 2126.93 mpp[tiflash] or(lt(Column#5, 18), gt(test.t.b, 1))", + " └─Projection 2658.67 mpp[tiflash] Column#5, test.t.b", + " └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#5, funcs:firstrow(test.t.b)->test.t.b", + " └─ExchangeReceiver 3323.33 mpp[tiflash] ", + " └─ExchangeSender 3323.33 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 60)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "WITH CTE AS (SELECT /*+ MPP_2PHASE_AGG() */ count(*) as a, b FROM t WHERE t.a < 60 group by b) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "HashAgg 3403.09 root group by:Column#10, Column#11, funcs:firstrow(Column#10)->Column#10, funcs:firstrow(Column#11)->Column#11", + "└─Union 3403.09 root ", + " ├─Selection 1701.55 root lt(Column#6, 18)", + " │ └─CTEFullScan 2126.93 root CTE:cte data:CTE_0", + " └─Selection 1701.55 root gt(test.t.b, 1)", + " └─CTEFullScan 2126.93 root CTE:cte data:CTE_0", + "CTE_0 2126.93 root Non-Recursive CTE", + "└─TableReader(Seed Part) 2126.93 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 2126.93 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection 2126.93 mpp[tiflash] or(lt(Column#5, 18), gt(test.t.b, 1))", + " └─Projection 2658.67 mpp[tiflash] Column#5, test.t.b", + " └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:sum(Column#22)->Column#5, funcs:firstrow(test.t.b)->test.t.b", + " └─ExchangeReceiver 2658.67 mpp[tiflash] ", + " └─ExchangeSender 2658.67 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#22", + " └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 60)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "WITH CTE AS (SELECT /*+ shuffle_join(t1, t) */ t.a, t.b FROM t join t t1 where t.a = t1.a) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "HashAgg 7095.48 root group by:Column#13, Column#14, funcs:firstrow(Column#13)->Column#13, funcs:firstrow(Column#14)->Column#14", + "└─Union 11086.68 root ", + " ├─Selection 5543.34 root lt(test.t.a, 18)", + " │ └─CTEFullScan 6929.18 root CTE:cte data:CTE_0", + " └─Selection 5543.34 root gt(test.t.b, 1)", + " └─CTEFullScan 6929.18 root CTE:cte data:CTE_0", + "CTE_0 6929.18 root Non-Recursive CTE", + "└─TableReader(Seed Part) 6929.18 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 6929.18 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 6929.18 mpp[tiflash] test.t.a, test.t.b", + " └─HashJoin 6929.18 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)], other cond:or(lt(test.t.a, 18), gt(test.t.b, 1))", + " ├─ExchangeReceiver(Build) 5543.34 mpp[tiflash] ", + " │ └─ExchangeSender 5543.34 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 5543.34 mpp[tiflash] not(isnull(test.t.a)), or(lt(test.t.a, 18), gt(test.t.b, 1))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "WITH CTE AS (SELECT /*+ broadcast_join(t1, t) */ t.a, t.b FROM t join t t1 where t.a = t1.a) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "HashAgg 7095.48 root group by:Column#13, Column#14, funcs:firstrow(Column#13)->Column#13, funcs:firstrow(Column#14)->Column#14", + "└─Union 11086.68 root ", + " ├─Selection 5543.34 root lt(test.t.a, 18)", + " │ └─CTEFullScan 6929.18 root CTE:cte data:CTE_0", + " └─Selection 5543.34 root gt(test.t.b, 1)", + " └─CTEFullScan 6929.18 root CTE:cte data:CTE_0", + "CTE_0 6929.18 root Non-Recursive CTE", + "└─TableReader(Seed Part) 6929.18 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 6929.18 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 6929.18 mpp[tiflash] test.t.a, test.t.b", + " └─HashJoin 6929.18 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)], other cond:or(lt(test.t.a, 18), gt(test.t.b, 1))", + " ├─ExchangeReceiver(Build) 5543.34 mpp[tiflash] ", + " │ └─ExchangeSender 5543.34 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 5543.34 mpp[tiflash] not(isnull(test.t.a)), or(lt(test.t.a, 18), gt(test.t.b, 1))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "WITH CTE AS (SELECT /*+ MERGE(), MPP_1PHASE_AGG() */ count(*) as a, b FROM t WHERE t.a < 60 group by b) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "TableReader 3013.16 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 3013.16 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 3013.16 mpp[tiflash] Column#20, Column#21", + " └─HashAgg 3013.16 mpp[tiflash] group by:Column#20, Column#21, funcs:firstrow(Column#20)->Column#20, funcs:firstrow(Column#21)->Column#21", + " └─ExchangeReceiver 3013.16 mpp[tiflash] ", + " └─ExchangeSender 3013.16 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#20, collate: binary], [name: Column#21, collate: binary]", + " └─Union 3013.16 mpp[tiflash] ", + " ├─Selection 2126.93 mpp[tiflash] lt(Column#12, 18)", + " │ └─Projection 2658.67 mpp[tiflash] Column#12, test.t.b", + " │ └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#12, funcs:firstrow(test.t.b)->test.t.b", + " │ └─ExchangeReceiver 3323.33 mpp[tiflash] ", + " │ └─ExchangeSender 3323.33 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 60)", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo", + " └─Projection 886.22 mpp[tiflash] Column#19->Column#20, test.t.b->Column#21", + " └─HashAgg 886.22 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#19, funcs:firstrow(test.t.b)->test.t.b", + " └─ExchangeReceiver 1107.78 mpp[tiflash] ", + " └─ExchangeSender 1107.78 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " └─Selection 1107.78 mpp[tiflash] gt(test.t.b, 1), lt(test.t.a, 60)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "WITH CTE AS (SELECT /*+ MERGE(), MPP_2PHASE_AGG() */ count(*) as a, b FROM t WHERE t.a < 60 group by b) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "TableReader 3013.16 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 3013.16 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 3013.16 mpp[tiflash] Column#20, Column#21", + " └─HashAgg 3013.16 mpp[tiflash] group by:Column#20, Column#21, funcs:firstrow(Column#20)->Column#20, funcs:firstrow(Column#21)->Column#21", + " └─ExchangeReceiver 3013.16 mpp[tiflash] ", + " └─ExchangeSender 3013.16 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#20, collate: binary], [name: Column#21, collate: binary]", + " └─Union 3013.16 mpp[tiflash] ", + " ├─Selection 2126.93 mpp[tiflash] lt(Column#12, 18)", + " │ └─Projection 2658.67 mpp[tiflash] Column#12, test.t.b", + " │ └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:sum(Column#32)->Column#12, funcs:firstrow(test.t.b)->test.t.b", + " │ └─ExchangeReceiver 2658.67 mpp[tiflash] ", + " │ └─ExchangeSender 2658.67 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " │ └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#32", + " │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 60)", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo", + " └─Projection 886.22 mpp[tiflash] Column#19->Column#20, test.t.b->Column#21", + " └─HashAgg 886.22 mpp[tiflash] group by:test.t.b, funcs:sum(Column#46)->Column#19, funcs:firstrow(test.t.b)->test.t.b", + " └─ExchangeReceiver 886.22 mpp[tiflash] ", + " └─ExchangeSender 886.22 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]", + " └─HashAgg 886.22 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#46", + " └─Selection 1107.78 mpp[tiflash] gt(test.t.b, 1), lt(test.t.a, 60)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "WITH CTE AS (SELECT /*+ MERGE(), shuffle_join(t1, t) */ t.a, t.b FROM t join t t1 where t.a = t1.a) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "TableReader 5322.67 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 5322.67 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 5322.67 mpp[tiflash] Column#29, Column#30", + " └─HashAgg 5322.67 mpp[tiflash] group by:Column#29, Column#30, funcs:firstrow(Column#29)->Column#29, funcs:firstrow(Column#30)->Column#30", + " └─ExchangeReceiver 5322.67 mpp[tiflash] ", + " └─ExchangeSender 5322.67 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#29, collate: binary], [name: Column#30, collate: binary]", + " └─HashAgg 5322.67 mpp[tiflash] group by:Column#29, Column#30, ", + " └─Union 8316.67 mpp[tiflash] ", + " ├─Projection 4154.17 mpp[tiflash] test.t.a->Column#29, test.t.b->Column#30", + " │ └─HashJoin 4154.17 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " │ ├─ExchangeReceiver(Build) 3323.33 mpp[tiflash] ", + " │ │ └─ExchangeSender 3323.33 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 18), not(isnull(test.t.a))", + " │ │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo", + " │ └─ExchangeReceiver(Probe) 3323.33 mpp[tiflash] ", + " │ └─ExchangeSender 3323.33 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 18), not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Projection 4162.50 mpp[tiflash] test.t.a->Column#29, test.t.b->Column#30", + " └─HashJoin 4162.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 3330.00 mpp[tiflash] ", + " │ └─ExchangeSender 3330.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 3330.00 mpp[tiflash] gt(test.t.b, 1), not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]There are no matching table names for (t1, t) in optimizer hint /*+ SHUFFLE_JOIN(t1, t, t1, t) */ or /*+ SHUFFLE_JOIN(t1, t, t1, t) */. Maybe you can use the table alias name", + "[planner:1815]There are no matching table names for (t1, t, t1, t) in optimizer hint /*+ SHUFFLE_JOIN(t1, t, t1, t, t1, t) */ or /*+ SHUFFLE_JOIN(t1, t, t1, t, t1, t) */. Maybe you can use the table alias name" + ] + }, + { + "SQL": "WITH CTE AS (SELECT /*+ MERGE(), broadcast_join(t1, t) */ t.a, t.b FROM t join t t1 where t.a = t1.a) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;", + "Plan": [ + "TableReader 5322.67 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 5322.67 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 5322.67 mpp[tiflash] Column#29, Column#30", + " └─HashAgg 5322.67 mpp[tiflash] group by:Column#29, Column#30, funcs:firstrow(Column#29)->Column#29, funcs:firstrow(Column#30)->Column#30", + " └─ExchangeReceiver 5322.67 mpp[tiflash] ", + " └─ExchangeSender 5322.67 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#29, collate: binary], [name: Column#30, collate: binary]", + " └─HashAgg 5322.67 mpp[tiflash] group by:Column#29, Column#30, ", + " └─Union 8316.67 mpp[tiflash] ", + " ├─Projection 4154.17 mpp[tiflash] test.t.a->Column#29, test.t.b->Column#30", + " │ └─HashJoin 4154.17 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " │ ├─ExchangeReceiver(Build) 3323.33 mpp[tiflash] ", + " │ │ └─ExchangeSender 3323.33 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 18), not(isnull(test.t.a))", + " │ │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo", + " │ └─Selection(Probe) 3323.33 mpp[tiflash] lt(test.t.a, 18), not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Projection 4162.50 mpp[tiflash] test.t.a->Column#29, test.t.b->Column#30", + " └─HashJoin 4162.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 3330.00 mpp[tiflash] ", + " │ └─ExchangeSender 3330.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 3330.00 mpp[tiflash] gt(test.t.b, 1), not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]There are no matching table names for (t1, t) in optimizer hint /*+ BROADCAST_JOIN(t1, t, t1, t) */ or /*+ TIDB_BCJ(t1, t, t1, t) */. Maybe you can use the table alias name", + "[planner:1815]There are no matching table names for (t1, t, t1, t) in optimizer hint /*+ BROADCAST_JOIN(t1, t, t1, t, t1, t) */ or /*+ TIDB_BCJ(t1, t, t1, t, t1, t) */. Maybe you can use the table alias name" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_build(t2) */ * from t t1 left join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] left outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_build(t2), hash_join_probe(t2) */ * from t t1 left join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] left outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Join hints are conflict, you can only specify one type of join" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_build(t1) */ * from t t1 right join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] right outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_probe(t2) */ * from t t1 left join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] left outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Some HASH_JOIN_BUILD and HASH_JOIN_PROBE hints cannot be utilized for MPP joins, please check the hints", + "[planner:1815]Some HASH_JOIN_BUILD and HASH_JOIN_PROBE hints cannot be utilized for MPP joins, please check the hints" + ] + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), broadcast_join(t1, t2), hash_join_probe(t1) */ * from t t1 right join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] right outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Some HASH_JOIN_BUILD and HASH_JOIN_PROBE hints cannot be utilized for MPP joins, please check the hints", + "[planner:1815]Some HASH_JOIN_BUILD and HASH_JOIN_PROBE hints cannot be utilized for MPP joins, please check the hints" + ] + }, + { + "SQL": "set @@session.tidb_opt_mpp_outer_join_fixed_build_side = 1", + "Plan": null, + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_build(t2) */ * from t t1 left join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] left outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_build(t1) */ * from t t1 right join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] right outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_probe(t2) */ * from t t1 left join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] left outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_probe(t1) */ * from t t1 right join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] right outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "set @@session.tidb_opt_mpp_outer_join_fixed_build_side = 0", + "Plan": null, + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_build(t2) */ * from t t1 left join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] left outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_build(t1) */ * from t t1 right join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] right outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_probe(t2) */ * from t t1 left join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] left outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ read_from_storage(tiflash[t1, t2]), shuffle_join(t1, t2), hash_join_probe(t1) */ * from t t1 right join t t2 on t1.a=t2.a", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] right outer join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ shuffle_join(t1, t2@sel_2), hash_join_build(t2@sel_2) */ a from t t1 where t1.a>1 or t1.a in (select a from t t2);", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a", + " └─Selection 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#9)", + " └─HashJoin 10000.00 mpp[tiflash] CARTESIAN left outer semi join, other cond:eq(test.t.a, test.t.a)", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint" + ] + }, + { + "SQL": "select /*+ shuffle_join(t1, t2@sel_2), hash_join_build(t1) */ a from t t1 where t1.a>1 or t1.a not in (select a from t t2);", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a", + " └─Selection 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#9)", + " └─HashJoin 10000.00 mpp[tiflash] Null-aware anti left outer semi join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Some HASH_JOIN_BUILD and HASH_JOIN_PROBE hints cannot be utilized for MPP joins, please check the hints", + "[planner:1815]We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint", + "[planner:1815]Some HASH_JOIN_BUILD and HASH_JOIN_PROBE hints cannot be utilized for MPP joins, please check the hints" + ] + }, + { + "SQL": "select /*+ shuffle_join(t1, t2@sel_2), hash_join_probe(t2@sel_2) */ a from t t1 where t1.a>1 or t1.a in (select a from t t2);", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a", + " └─Selection 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#9)", + " └─HashJoin 10000.00 mpp[tiflash] CARTESIAN left outer semi join, other cond:eq(test.t.a, test.t.a)", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Some HASH_JOIN_BUILD and HASH_JOIN_PROBE hints cannot be utilized for MPP joins, please check the hints", + "[planner:1815]We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for left outer semi join, please check the hint", + "[planner:1815]Some HASH_JOIN_BUILD and HASH_JOIN_PROBE hints cannot be utilized for MPP joins, please check the hints" + ] + }, + { + "SQL": "select /*+ shuffle_join(t1, t2@sel_2), hash_join_probe(t1) */ a from t t1 where t1.a>1 or t1.a not in (select a from t t2);", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a", + " └─Selection 8000.00 mpp[tiflash] or(gt(test.t.a, 1), Column#9)", + " └─HashJoin 10000.00 mpp[tiflash] Null-aware anti left outer semi join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]We can't use the HASH_JOIN_BUILD or HASH_JOIN_PROBE hint for anti left outer semi join, please check the hint" + ] + } + ] + }, + { + "Name": "TestMPPHintsScope", + "Cases": [ + { + "SQL": "set @@session.tidb_allow_mpp=true", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select /*+ MPP_1PHASE_AGG() */ a, sum(b) from t group by a, c", + "Plan": [ + "TableReader_31 8000.00 root MppVersion: 2, data:ExchangeSender_30", + "└─ExchangeSender_30 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection_5 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection_29 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg_27 8000.00 mpp[tiflash] group by:Column#10, Column#11, funcs:sum(Column#8)->Column#5, funcs:firstrow(Column#9)->test.t.a", + " └─Projection_32 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#8, test.t.a->Column#9, test.t.a->Column#10, test.t.c->Column#11", + " └─ExchangeReceiver_23 10000.00 mpp[tiflash] ", + " └─ExchangeSender_22 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─TableFullScan_21 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ MPP_2PHASE_AGG() */ a, sum(b) from t group by a, c", + "Plan": [ + "TableReader_35 8000.00 root MppVersion: 2, data:ExchangeSender_34", + "└─ExchangeSender_34 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection_5 8000.00 mpp[tiflash] test.t.a, Column#5", + " └─Projection_30 8000.00 mpp[tiflash] Column#5, test.t.a", + " └─HashAgg_31 8000.00 mpp[tiflash] group by:test.t.a, test.t.c, funcs:sum(Column#10)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─ExchangeReceiver_33 8000.00 mpp[tiflash] ", + " └─ExchangeSender_32 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary], [name: test.t.c, collate: binary]", + " └─HashAgg_29 8000.00 mpp[tiflash] group by:Column#13, Column#14, funcs:sum(Column#12)->Column#10", + " └─Projection_36 10000.00 mpp[tiflash] cast(test.t.b, decimal(10,0) BINARY)->Column#12, test.t.a->Column#13, test.t.c->Column#14", + " └─TableFullScan_21 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ shuffle_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader_22 12487.50 root MppVersion: 2, data:ExchangeSender_21", + "└─ExchangeSender_21 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_20 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_13(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_12 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection_11 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan_10 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver_17(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender_16 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection_15 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_14 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ broadcast_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader_20 12487.50 root MppVersion: 2, data:ExchangeSender_19", + "└─ExchangeSender_19 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_18 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_13(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_12 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_11 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan_10 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection_15(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_14 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "set @@session.tidb_enforce_mpp=true", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select /*+ hash_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader_69 12487.50 root MppVersion: 2, data:ExchangeSender_68", + "└─ExchangeSender_68 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_61 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_65(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_64 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_63 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan_62 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection_67(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_66 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ merge_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "MergeJoin_10 12487.50 root inner join, left key:test.t.a, right key:test.t.a", + "├─Projection_19(Build) 9990.00 root test.t.a, test.t.b, test.t.c", + "│ └─IndexLookUp_18 9990.00 root ", + "│ ├─IndexFullScan_16(Build) 9990.00 cop[tikv] table:t2, index:idx_a(a) keep order:true, stats:pseudo", + "│ └─TableRowIDScan_17(Probe) 9990.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─Projection_15(Probe) 9990.00 root test.t.a, test.t.b, test.t.c", + " └─IndexLookUp_14 9990.00 root ", + " ├─IndexFullScan_12(Build) 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " └─TableRowIDScan_13(Probe) 9990.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now.", + "MPP mode may be blocked because you have used hint to specify a join algorithm which is not supported by mpp now." + ] + }, + { + "SQL": "set @@session.tidb_enforce_mpp=false", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select /*+ hash_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader_69 12487.50 root MppVersion: 2, data:ExchangeSender_68", + "└─ExchangeSender_68 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_61 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_65(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_64 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_63 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan_62 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection_67(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_66 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ merge_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "MergeJoin_10 12487.50 root inner join, left key:test.t.a, right key:test.t.a", + "├─Projection_19(Build) 9990.00 root test.t.a, test.t.b, test.t.c", + "│ └─IndexLookUp_18 9990.00 root ", + "│ ├─IndexFullScan_16(Build) 9990.00 cop[tikv] table:t2, index:idx_a(a) keep order:true, stats:pseudo", + "│ └─TableRowIDScan_17(Probe) 9990.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─Projection_15(Probe) 9990.00 root test.t.a, test.t.b, test.t.c", + " └─IndexLookUp_14 9990.00 root ", + " ├─IndexFullScan_12(Build) 9990.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + " └─TableRowIDScan_13(Probe) 9990.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ read_from_storage(tiflash[t1, t2]) hash_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader_29 12487.50 root MppVersion: 2, data:ExchangeSender_28", + "└─ExchangeSender_28 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_21 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_25(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_24 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_23 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan_22 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection_27(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_26 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain select /*+ read_from_storage(tiflash[t1, t2]) merge_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "MergeJoin_11 12487.50 root inner join, left key:test.t.a, right key:test.t.a", + "├─Sort_21(Build) 9990.00 root test.t.a", + "│ └─TableReader_20 9990.00 root MppVersion: 2, data:ExchangeSender_19", + "│ └─ExchangeSender_19 9990.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─Selection_18 9990.00 mpp[tiflash] not(isnull(test.t.a))", + "│ └─TableFullScan_17 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo", + "└─Sort_16(Probe) 9990.00 root test.t.a", + " └─TableReader_15 9990.00 root MppVersion: 2, data:ExchangeSender_14", + " └─ExchangeSender_14 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection_13 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_12 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "set @@session.tidb_allow_mpp=false", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select /*+ MPP_1PHASE_AGG() */ a, sum(b) from t group by a, c", + "Plan": [ + "Projection_4 8000.00 root test.t.a, Column#5", + "└─HashAgg_10 8000.00 root group by:test.t.a, test.t.c, funcs:sum(Column#6)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─TableReader_11 8000.00 root data:HashAgg_5", + " └─HashAgg_5 8000.00 cop[tikv] group by:test.t.a, test.t.c, funcs:sum(test.t.b)->Column#6", + " └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]The agg can not push down to the MPP side, the MPP_1PHASE_AGG() hint is invalid" + ] + }, + { + "SQL": "explain select /*+ MPP_2PHASE_AGG() */ a, sum(b) from t group by a, c", + "Plan": [ + "Projection_4 8000.00 root test.t.a, Column#5", + "└─HashAgg_10 8000.00 root group by:test.t.a, test.t.c, funcs:sum(Column#6)->Column#5, funcs:firstrow(test.t.a)->test.t.a", + " └─TableReader_11 8000.00 root data:HashAgg_5", + " └─HashAgg_5 8000.00 cop[tikv] group by:test.t.a, test.t.c, funcs:sum(test.t.b)->Column#6", + " └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]The agg can not push down to the MPP side, the MPP_2PHASE_AGG() hint is invalid" + ] + }, + { + "SQL": "explain select /*+ shuffle_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "HashJoin_37 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─TableReader_56(Build) 9990.00 root data:Selection_55", + "│ └─Selection_55 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan_54 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─TableReader_49(Probe) 9990.00 root data:Selection_48", + " └─Selection_48 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan_47 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]The join can not push down to the MPP side, the shuffle_join() hint is invalid" + ] + }, + { + "SQL": "explain select /*+ broadcast_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "HashJoin_37 12487.50 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─TableReader_56(Build) 9990.00 root data:Selection_55", + "│ └─Selection_55 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan_54 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─TableReader_49(Probe) 9990.00 root data:Selection_48", + " └─Selection_48 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan_47 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]The join can not push down to the MPP side, the broadcast_join() hint is invalid" + ] + } + ] + }, + { + "Name": "TestMPPBCJModel", + "Cases": [ + { + "SQL": "set @@session.tidb_allow_mpp=true", + "Plan": null, + "Warn": null + }, + { + "SQL": "set @@session.tidb_prefer_broadcast_join_by_exchange_data_size=0", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader_79 12487.50 root MppVersion: 2, data:ExchangeSender_78", + "└─ExchangeSender_78 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_77 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_44(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_43 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_42 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan_41 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection_46(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_45 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "set @@session.tidb_prefer_broadcast_join_by_exchange_data_size=1", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader_81 12487.50 root MppVersion: 2, data:ExchangeSender_80", + "└─ExchangeSender_80 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_79 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_44(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_43 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection_42 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan_41 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver_48(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender_47 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection_46 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_45 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, + { + "Name": "TestMPPPreferBCJ", + "Cases": [ + { + "SQL": "explain select * from t1, t2 where t1.a=t2.b", + "Plan": [ + "TableReader_36 1.00 root MppVersion: 2, data:ExchangeSender_35", + "└─ExchangeSender_35 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_34 1.00 mpp[tiflash] inner join, equal:[eq(test.t1.a, test.t2.b)]", + " ├─ExchangeReceiver_15(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender_14 1.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_13 1.00 mpp[tiflash] not(isnull(test.t1.a))", + " │ └─TableFullScan_12 1.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false", + " └─Selection_17(Probe) 8.00 mpp[tiflash] not(isnull(test.t2.b))", + " └─TableFullScan_16 8.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false" + ], + "Warn": null + }, + { + "SQL": "set @@session.tidb_prefer_broadcast_join_by_exchange_data_size=1", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t1, t2 where t1.a=t2.b", + "Plan": [ + "TableReader_38 1.00 root MppVersion: 2, data:ExchangeSender_37", + "└─ExchangeSender_37 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_36 1.00 mpp[tiflash] inner join, equal:[eq(test.t1.a, test.t2.b)]", + " ├─ExchangeReceiver_15(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender_14 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t1.a, collate: binary]", + " │ └─Selection_13 1.00 mpp[tiflash] not(isnull(test.t1.a))", + " │ └─TableFullScan_12 1.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false", + " └─ExchangeReceiver_19(Probe) 8.00 mpp[tiflash] ", + " └─ExchangeSender_18 8.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t2.b, collate: binary]", + " └─Selection_17 8.00 mpp[tiflash] not(isnull(test.t2.b))", + " └─TableFullScan_16 8.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false" + ], + "Warn": null + }, + { + "SQL": "insert into t2 values (9); analyze table t2;", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t1, t2 where t1.a=t2.b", + "Plan": [ + "TableReader_36 1.00 root MppVersion: 2, data:ExchangeSender_35", + "└─ExchangeSender_35 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_34 1.00 mpp[tiflash] inner join, equal:[eq(test.t1.a, test.t2.b)]", + " ├─ExchangeReceiver_15(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender_14 1.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_13 1.00 mpp[tiflash] not(isnull(test.t1.a))", + " │ └─TableFullScan_12 1.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false", + " └─Selection_17(Probe) 9.00 mpp[tiflash] not(isnull(test.t2.b))", + " └─TableFullScan_16 9.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false" + ], + "Warn": null + } + ] + }, + { + "Name": "TestMPPBCJModelOneTiFlash", + "Cases": [ + { + "SQL": "set @@session.tidb_allow_mpp=true", + "Plan": null, + "Warn": null + }, + { + "SQL": "set @@session.tidb_prefer_broadcast_join_by_exchange_data_size=0", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader_81 12487.50 root MppVersion: 2, data:ExchangeSender_80", + "└─ExchangeSender_80 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_79 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_44(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_43 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " │ └─Selection_42 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan_41 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver_48(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender_47 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─Selection_46 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_45 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "set @@session.tidb_prefer_broadcast_join_by_exchange_data_size=1", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t t1, t t2 where t1.a=t2.a", + "Plan": [ + "TableReader_79 12487.50 root MppVersion: 2, data:ExchangeSender_78", + "└─ExchangeSender_78 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_77 12487.50 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.a)]", + " ├─ExchangeReceiver_44(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender_43 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_42 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " │ └─TableFullScan_41 10000.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection_46(Probe) 9990.00 mpp[tiflash] not(isnull(test.t.a))", + " └─TableFullScan_45 10000.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, + { + "Name": "TestMPPRightSemiJoin", + "Cases": [ + { + "SQL": "set @@session.tidb_allow_mpp=true", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t1 where exists (select * from t2 where t1.a=t2.b)", + "Plan": [ + "TableReader_36 0.80 root MppVersion: 2, data:ExchangeSender_35", + "└─ExchangeSender_35 0.80 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_34 0.80 mpp[tiflash] semi join, equal:[eq(test.t1.a, test.t2.b)]", + " ├─ExchangeReceiver_17(Build) 8.00 mpp[tiflash] ", + " │ └─ExchangeSender_16 8.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_15 8.00 mpp[tiflash] not(isnull(test.t2.b))", + " │ └─TableFullScan_14 8.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false", + " └─Selection_13(Probe) 1.00 mpp[tiflash] not(isnull(test.t1.a))", + " └─TableFullScan_12 1.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false" + ], + "Warn": null + }, + { + "SQL": "set @@session.tidb_prefer_broadcast_join_by_exchange_data_size=0", + "Plan": null, + "Warn": null + }, + { + "SQL": "set @@session.tidb_broadcast_join_threshold_size=0", + "Plan": null, + "Warn": null + }, + { + "SQL": "set @@session.tidb_broadcast_join_threshold_count=0", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t1 where exists (select * from t2 where t1.a=t2.b)", + "Plan": [ + "TableReader_38 0.80 root MppVersion: 2, data:ExchangeSender_37", + "└─ExchangeSender_37 0.80 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_36 0.80 mpp[tiflash] semi join, equal:[eq(test.t1.a, test.t2.b)]", + " ├─ExchangeReceiver_15(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender_14 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t1.a, collate: binary]", + " │ └─Selection_13 1.00 mpp[tiflash] not(isnull(test.t1.a))", + " │ └─TableFullScan_12 1.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false", + " └─ExchangeReceiver_19(Probe) 8.00 mpp[tiflash] ", + " └─ExchangeSender_18 8.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t2.b, collate: binary]", + " └─Selection_17 8.00 mpp[tiflash] not(isnull(test.t2.b))", + " └─TableFullScan_16 8.00 mpp[tiflash] table:t2 pushed down filter:empty, keep order:false" + ], + "Warn": null + } + ] + }, + { + "Name": "TestMPPRightOuterJoin", + "Cases": [ + { + "SQL": "set @@session.tidb_allow_mpp=true", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t1 right join t2 on t1.a=t2.b and t1.c < t2.d", + "Plan": [ + "TableReader_32 3.00 root MppVersion: 2, data:ExchangeSender_31", + "└─ExchangeSender_31 3.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_30 3.00 mpp[tiflash] right outer join, equal:[eq(test.t1.a, test.t2.b)], other cond:lt(test.t1.c, test.t2.d)", + " ├─ExchangeReceiver_14(Build) 5.00 mpp[tiflash] ", + " │ └─ExchangeSender_13 5.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection_12 5.00 mpp[tiflash] not(isnull(test.t1.a)), not(isnull(test.t1.c))", + " │ └─TableFullScan_11 5.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false", + " └─TableFullScan_15(Probe) 3.00 mpp[tiflash] table:t2 keep order:false" + ], + "Warn": null + }, + { + "SQL": "set @@session.tidb_prefer_broadcast_join_by_exchange_data_size=0", + "Plan": null, + "Warn": null + }, + { + "SQL": "set @@session.tidb_broadcast_join_threshold_size=0", + "Plan": null, + "Warn": null + }, + { + "SQL": "set @@session.tidb_broadcast_join_threshold_count=0", + "Plan": null, + "Warn": null + }, + { + "SQL": "explain select * from t1 right join t2 on t1.a=t2.b and t1.c < t2.d", + "Plan": [ + "TableReader_34 3.00 root MppVersion: 2, data:ExchangeSender_33", + "└─ExchangeSender_33 3.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin_32 3.00 mpp[tiflash] right outer join, equal:[eq(test.t1.a, test.t2.b)], other cond:lt(test.t1.c, test.t2.d)", + " ├─ExchangeReceiver_17(Build) 3.00 mpp[tiflash] ", + " │ └─ExchangeSender_16 3.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t2.b, collate: binary]", + " │ └─TableFullScan_15 3.00 mpp[tiflash] table:t2 keep order:false", + " └─ExchangeReceiver_14(Probe) 5.00 mpp[tiflash] ", + " └─ExchangeSender_13 5.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t1.a, collate: binary]", + " └─Selection_12 5.00 mpp[tiflash] not(isnull(test.t1.a)), not(isnull(test.t1.c))", + " └─TableFullScan_11 5.00 mpp[tiflash] table:t1 pushed down filter:empty, keep order:false" + ], + "Warn": null + } + ] + }, + { + "Name": "TestIssue37520", + "Cases": [ + { + "SQL": "select /*+ inl_join(t1@sel_2) */ a, (select b from t1 where t1.a = t2.b) from t2;", + "Plan": [ + "IndexJoin 12500.00 root left outer join, inner:TableReader, outer key:test.t2.b, inner key:test.t1.a, equal cond:eq(test.t2.b, test.t1.a)", + "├─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:TableRangeScan", + " └─TableRangeScan 10000.00 cop[tikv] table:t1 range: decided by [test.t2.b], keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "select /*+ inl_join(t2) */ a, (select b from t1 where t1.a = t2.b) from t2;", + "Plan": [ + "HashJoin 12500.00 root left outer join, equal:[eq(test.t2.b, test.t1.a)]", + "├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Optimizer Hint /*+ INL_JOIN(t2) */ or /*+ TIDB_INLJ(t2) */ is inapplicable" + ] + }, + { + "SQL": "select /*+ inl_join(t2@sel_2) */ * from t1 where exists ( select /*+ semi_join_rewrite() */ * from t2 where t1.a = t2.a);", + "Plan": [ + "MergeJoin 9990.00 root inner join, left key:test.t1.a, right key:test.t2.a", + "├─StreamAgg(Build) 7992.00 root group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a", + "│ └─IndexReader 7992.00 root index:StreamAgg", + "│ └─StreamAgg 7992.00 cop[tikv] group by:test.t2.a, ", + "│ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:ia(a) keep order:true, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo" + ], + "Warn": [ + "[planner:1815]Optimizer Hint /*+ INL_JOIN(t2) */ or /*+ TIDB_INLJ(t2) */ is inapplicable" + ] + }, + { + "SQL": "select /*+ inl_join(t1) */ * from t1 where exists ( select /*+ semi_join_rewrite() */ * from t2 where t1.a = t2.a);", + "Plan": [ + "IndexJoin 9990.00 root inner join, inner:TableReader, outer key:test.t2.a, inner key:test.t1.a, equal cond:eq(test.t2.a, test.t1.a)", + "├─StreamAgg(Build) 7992.00 root group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a", + "│ └─IndexReader 7992.00 root index:StreamAgg", + "│ └─StreamAgg 7992.00 cop[tikv] group by:test.t2.a, ", + "│ └─IndexFullScan 9990.00 cop[tikv] table:t2, index:ia(a) keep order:true, stats:pseudo", + "└─TableReader(Probe) 7992.00 root data:TableRangeScan", + " └─TableRangeScan 7992.00 cop[tikv] table:t1 range: decided by [test.t2.a], keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, + { + "Name": "TestHintScope", + "Cases": [ + { + "SQL": "select /*+ MERGE_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(t3) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ MERGE_JOIN(test.t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(test.t3) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ MERGE_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)->Sort}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "IndexJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ INL_JOIN(test.t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(test.t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "IndexJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ MERGE_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "IndexJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ MERGE_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "RightHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ HASH_JOIN(test.t1) */ t1.a, t1.b from t t1, (select /*+ MERGE_JOIN(test.t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "RightHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "RightHashJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.c,test.t.a)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ MERGE_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "MergeInnerJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "IndexJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Best": "RightHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)}(test.t.a,test.t.a)" + }, + { + "SQL": "select /*+ HASH_JOIN(@sel_2 t1@sel_2, t2@sel_2), MERGE_JOIN(@sel_1 t1@sel_1, t2@sel_1) */ * from (select t1.a, t1.b from t t1, t t2 where t1.a = t2.a) t1, t t2 where t1.b = t2.b", + "Best": "MergeInnerJoin{LeftHashJoin{TableReader(Table(t))->IndexReader(Index(t.f)[[NULL,+inf]])}(test.t.a,test.t.a)->Sort->TableReader(Table(t))->Sort}(test.t.b,test.t.b)" + }, + { + "SQL": "select /*+ STREAM_AGG() */ s, count(s) from (select /*+ HASH_AGG() */ sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->Projection->HashAgg->Sort->StreamAgg->Projection" + }, + { + "SQL": "select /*+ HASH_AGG() */ s, count(s) from (select /*+ STREAM_AGG() */ sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->Sort->Projection->StreamAgg->HashAgg->Projection" + }, + { + "SQL": "select /*+ HASH_AGG() */ s, count(s) from (select sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->Projection->HashAgg->HashAgg->Projection" + }, + { + "SQL": "select /*+ STREAM_AGG() */ s, count(s) from (select sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->Projection->HashAgg->Sort->StreamAgg->Projection" + } + ] + }, + { + "Name": "TestIndexHint", + "Cases": [ + { + "SQL": "select /*+ USE_INDEX(t, c_d_e) */ * from t", + "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`), no_order_index(@`sel_1` `test`.`t` `c_d_e`)" + }, + { + "SQL": "select /*+ USE_INDEX(test.t, c_d_e) */ * from t", + "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`), no_order_index(@`sel_1` `test`.`t` `c_d_e`)" + }, + { + "SQL": "select /*+ IGNORE_INDEX(t, c_d_e) */ c from t order by c", + "Best": "TableReader(Table(t))->Sort", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ IGNORE_INDEX(test.t, c_d_e) */ c from t order by c", + "Best": "TableReader(Table(t))->Sort", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t, c_d_e) */ * from t", + "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`), no_order_index(@`sel_1` `test`.`t` `c_d_e`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(test.t, c_d_e) */ * from t", + "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`), no_order_index(@`sel_1` `test`.`t` `c_d_e`)" + }, + { + "SQL": "select /*+ USE_INDEX(t, c_d_e) */ * from t t1", + "Best": "TableReader(Table(t))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t1` ), no_order_index(@`sel_1` `test`.`t1` `primary`)" + }, + { + "SQL": "select /*+ IGNORE_INDEX(t, c_d_e) */ t1.c from t t1 order by t1.c", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t1` `c_d_e`), order_index(@`sel_1` `test`.`t1` `c_d_e`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t, c_d_e) */ * from t t1", + "Best": "TableReader(Table(t))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t1` ), no_order_index(@`sel_1` `test`.`t1` `primary`)" + }, + { + "SQL": "select /*+ USE_INDEX(t1, c_d_e) */ * from t t1", + "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t1` `c_d_e`), no_order_index(@`sel_1` `test`.`t1` `c_d_e`)" + }, + { + "SQL": "select /*+ IGNORE_INDEX(t1, c_d_e) */ t1.c from t t1 order by t1.c", + "Best": "TableReader(Table(t))->Sort", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t1` ), no_order_index(@`sel_1` `test`.`t1` `primary`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t1, c_d_e) */ * from t t1", + "Best": "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t1` `c_d_e`), no_order_index(@`sel_1` `test`.`t1` `c_d_e`)" + }, + { + "SQL": "select /*+ USE_INDEX(t1, c_d_e), USE_INDEX(t2, f) */ * from t t1, t t2 where t1.a = t2.b", + "Best": "LeftHashJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))}(test.t.a,test.t.b)", + "HasWarn": false, + "Hints": "hash_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` `c_d_e`), no_order_index(@`sel_1` `test`.`t1` `c_d_e`), use_index(@`sel_1` `test`.`t2` `f`), no_order_index(@`sel_1` `test`.`t2` `f`)" + }, + { + "SQL": "select /*+ IGNORE_INDEX(t1, c_d_e), IGNORE_INDEX(t2, f), HASH_JOIN(t1) */ * from t t1, t t2 where t1.a = t2.b", + "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.b)", + "HasWarn": false, + "Hints": "hash_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` ), no_order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_1` `test`.`t2` ), no_order_index(@`sel_1` `test`.`t2` `primary`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t1, c_d_e), FORCE_INDEX(t2, f) */ * from t t1, t t2 where t1.a = t2.b", + "Best": "LeftHashJoin{IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))->IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))}(test.t.a,test.t.b)", + "HasWarn": false, + "Hints": "hash_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` `c_d_e`), no_order_index(@`sel_1` `test`.`t1` `c_d_e`), use_index(@`sel_1` `test`.`t2` `f`), no_order_index(@`sel_1` `test`.`t2` `f`)" + }, + { + "SQL": "select /*+ USE_INDEX(t, c_d_e, f, g) */ * from t order by f", + "Best": "IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `f`), order_index(@`sel_1` `test`.`t` `f`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t, c_d_e, f, g) */ * from t order by f", + "Best": "IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `f`), order_index(@`sel_1` `test`.`t` `f`)" + }, + { + "SQL": "select /*+ USE_INDEX(t) */ f from t where f > 10", + "Best": "TableReader(Table(t)->Sel([gt(test.t.f, 10)]))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t) */ f from t where f > 10", + "Best": "TableReader(Table(t)->Sel([gt(test.t.f, 10)]))", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ USE_INDEX(t, no_such_index) */ * from t", + "Best": "TableReader(Table(t))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ IGNORE_INDEX(t, no_such_index) */ * from t", + "Best": "TableReader(Table(t))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t, no_such_index) */ * from t", + "Best": "TableReader(Table(t))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ USE_INDEX(t, c_d_e), IGNORE_INDEX(t, f) */ c from t order by c", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`), order_index(@`sel_1` `test`.`t` `c_d_e`)" + }, + { + "SQL": "select /*+ USE_INDEX(t, f), IGNORE_INDEX(t, f) */ c from t order by c", + "Best": "TableReader(Table(t))->Sort", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ USE_INDEX(t, c_d_e), IGNORE_INDEX(t, c_d_e) */ c from t order by c", + "Best": "TableReader(Table(t))->Sort", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ USE_INDEX(t, c_d_e, f), IGNORE_INDEX(t, c_d_e) */ c from t order by c", + "Best": "IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))->Sort", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `f`), no_order_index(@`sel_1` `test`.`t` `f`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t, c_d_e), IGNORE_INDEX(t, f) */ c from t order by c", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `c_d_e`), order_index(@`sel_1` `test`.`t` `c_d_e`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t, f), IGNORE_INDEX(t, f) */ c from t order by c", + "Best": "TableReader(Table(t))->Sort", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t, c_d_e), IGNORE_INDEX(t, c_d_e) */ c from t order by c", + "Best": "TableReader(Table(t))->Sort", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ FORCE_INDEX(t, c_d_e, f), IGNORE_INDEX(t, c_d_e) */ c from t order by c", + "Best": "IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))->Sort", + "HasWarn": false, + "Hints": "use_index(@`sel_1` `test`.`t` `f`), no_order_index(@`sel_1` `test`.`t` `f`)" + } + ] + }, + { + "Name": "TestIndexMergeHint", + "Cases": [ + { + "SQL": "select /*+ USE_INDEX_MERGE(t, c_d_e, f_g) */ * from t where c < 1 or f > 2", + "Best": "IndexMergeReader(PartialPlans->[Index(t.c_d_e)[[-inf,1)], Index(t.f_g)[(2,+inf]]], TablePlan->Table(t))", + "HasWarn": false, + "Hints": "use_index_merge(@`sel_1` `t` `c_d_e`, `f_g`)" + }, + { + "SQL": "select /*+ USE_INDEX_MERGE(t, primary, f_g) */ * from t where a < 1 or f > 2", + "Best": "IndexMergeReader(PartialPlans->[Table(t), Index(t.f_g)[(2,+inf]]], TablePlan->Table(t))", + "HasWarn": false, + "Hints": "use_index_merge(@`sel_1` `t` `primary`, `f_g`)" + }, + { + "SQL": "select /*+ USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2", + "Best": "IndexMergeReader(PartialPlans->[Table(t), Index(t.f_g)[(2,+inf]]], TablePlan->Table(t))", + "HasWarn": false, + "Hints": "use_index_merge(@`sel_1` `t` `primary`, `f_g`)" + }, + { + "SQL": "select /*+ NO_INDEX_MERGE(), USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2", + "Best": "TableReader(Table(t)->Sel([or(lt(test.t.a, 1), gt(test.t.f, 2))]))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ USE_INDEX_MERGE(t1, c_d_e, f_g) */ * from t where c < 1 or f > 2", + "Best": "TableReader(Table(t)->Sel([or(lt(test.t.c, 1), gt(test.t.f, 2))]))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ NO_INDEX_MERGE(), USE_INDEX_MERGE(t, primary, f_g, c_d_e) */ * from t where a < 1 or f > 2", + "Best": "TableReader(Table(t)->Sel([or(lt(test.t.a, 1), gt(test.t.f, 2))]))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ USE_INDEX_MERGE(t) USE_INDEX_MERGE(t) */ * from t where c < 1 or f > 2", + "Best": "IndexMergeReader(PartialPlans->[Index(t.c_d_e)[[-inf,1)], Index(t.f)[(2,+inf]]], TablePlan->Table(t))", + "HasWarn": false, + "Hints": "use_index_merge(@`sel_1` `t` `c_d_e`, `f`)" + }, + { + "SQL": "select /*+ USE_INDEX_MERGE(db2.t) */ * from t where c < 1 or f > 2", + "Best": "TableReader(Table(t)->Sel([or(lt(test.t.c, 1), gt(test.t.f, 2))]))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + }, + { + "SQL": "select /*+ USE_INDEX_MERGE(db2.t, c_d_e, f_g) */ * from t where c < 1 or f > 2", + "Best": "TableReader(Table(t)->Sel([or(lt(test.t.c, 1), gt(test.t.f, 2))]))", + "HasWarn": true, + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`)" + } + ] + }, + { + "Name": "TestRefine", + "Cases": [ + { + "SQL": "select a from t where c is not null", + "Best": "IndexReader(Index(t.f)[[NULL,+inf]])" + }, + { + "SQL": "select a from t where c >= 4", + "Best": "IndexReader(Index(t.c_d_e)[[4,+inf]])->Projection" + }, + { + "SQL": "select a from t where c <= 4", + "Best": "IndexReader(Index(t.c_d_e)[[-inf,4]])->Projection" + }, + { + "SQL": "select a from t where c = 4 and d = 5 and e = 6", + "Best": "PointGet(Index(t.c_d_e)[KindInt64 4 KindInt64 5 KindInt64 6])->Projection" + }, + { + "SQL": "select a from t where d = 4 and c = 5", + "Best": "IndexReader(Index(t.c_d_e)[[5 4,5 4]])->Projection" + }, + { + "SQL": "select a from t where c = 4 and e < 5", + "Best": "IndexReader(Index(t.c_d_e)[[4,4]]->Sel([lt(test.t.e, 5)]))->Projection" + }, + { + "SQL": "select a from t where c = 4 and d <= 5 and d > 3", + "Best": "IndexReader(Index(t.c_d_e)[(4 3,4 5]])->Projection" + }, + { + "SQL": "select a from t where d <= 5 and d > 3", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Sel([le(test.t.d, 5) gt(test.t.d, 3)]))->Projection" + }, + { + "SQL": "select a from t where c between 1 and 2", + "Best": "IndexReader(Index(t.c_d_e)[[1,2]])->Projection" + }, + { + "SQL": "select a from t where c not between 1 and 2", + "Best": "IndexReader(Index(t.c_d_e)[[-inf,1) (2,+inf]])->Projection" + }, + { + "SQL": "select a from t where c <= 5 and c >= 3 and d = 1", + "Best": "IndexReader(Index(t.c_d_e)[[3,5]]->Sel([eq(test.t.d, 1)]))->Projection" + }, + { + "SQL": "select a from t where c = 1 or c = 2 or c = 3", + "Best": "IndexReader(Index(t.c_d_e)[[1,3]])->Projection" + }, + { + "SQL": "select b from t where c = 1 or c = 2 or c = 3 or c = 4 or c = 5", + "Best": "TableReader(Table(t)->Sel([or(or(eq(test.t.c, 1), eq(test.t.c, 2)), or(eq(test.t.c, 3), or(eq(test.t.c, 4), eq(test.t.c, 5))))]))->Projection" + }, + { + "SQL": "select a from t where c = 5", + "Best": "IndexReader(Index(t.c_d_e)[[5,5]])->Projection" + }, + { + "SQL": "select a from t where c = 5 and b = 1", + "Best": "IndexLookUp(Index(t.c_d_e)[[5,5]], Table(t)->Sel([eq(test.t.b, 1)]))->Projection" + }, + { + "SQL": "select a from t where not a", + "Best": "PointGet(Handle(t.a)0)" + }, + { + "SQL": "select a from t where c in (1)", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection" + }, + { + "SQL": "select a from t where c in ('1')", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection" + }, + { + "SQL": "select a from t where c = 1.0", + "Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection" + }, + { + "SQL": "select a from t where c in (1) and d > 3", + "Best": "IndexReader(Index(t.c_d_e)[(1 3,1 +inf]])->Projection" + }, + { + "SQL": "select a from t where c in (1, 2, 3) and (d > 3 and d < 4 or d > 5 and d < 6)", + "Best": "Dual->Projection" + }, + { + "SQL": "select a from t where c in (1, 2, 3) and (d > 2 and d < 4 or d > 5 and d < 7)", + "Best": "IndexReader(Index(t.c_d_e)[[1 3,1 3] [1 6,1 6] [2 3,2 3] [2 6,2 6] [3 3,3 3] [3 6,3 6]])->Projection" + }, + { + "SQL": "select a from t where c in (1, 2, 3)", + "Best": "IndexReader(Index(t.c_d_e)[[1,1] [2,2] [3,3]])->Projection" + }, + { + "SQL": "select a from t where c in (1, 2, 3) and d in (1,2) and e = 1", + "Best": "BatchPointGet(Index(t.c_d_e)[[KindInt64 1 KindInt64 1 KindInt64 1] [KindInt64 1 KindInt64 2 KindInt64 1] [KindInt64 2 KindInt64 1 KindInt64 1] [KindInt64 2 KindInt64 2 KindInt64 1] [KindInt64 3 KindInt64 1 KindInt64 1] [KindInt64 3 KindInt64 2 KindInt64 1]])->Projection" + }, + { + "SQL": "select a from t where d in (1, 2, 3)", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Sel([in(test.t.d, 1, 2, 3)]))->Projection" + }, + { + "SQL": "select a from t where c not in (1)", + "Best": "IndexReader(Index(t.c_d_e)[[-inf,1) (1,+inf]])->Projection" + }, + { + "SQL": "select a from t use index(c_d_e) where c != 1", + "Best": "IndexReader(Index(t.c_d_e)[[-inf,1) (1,+inf]])->Projection" + }, + { + "SQL": "select a from t where c_str like ''", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"\",\"\"]]->Sel([like(test.t.c_str, , 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc'", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abc\"]]->Sel([like(test.t.c_str, abc, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str not like 'abc'", + "Best": "IndexReader(Index(t.c_d_e_str)[[NULL,+inf]]->Sel([not(like(test.t.c_str, abc, 92))]))->Projection" + }, + { + "SQL": "select a from t where not (c_str like 'abc' or c_str like 'abd')", + "Best": "IndexReader(Index(t.c_d_e_str)[[NULL,+inf]]->Sel([and(not(like(test.t.c_str, abc, 92)), not(like(test.t.c_str, abd, 92)))]))->Projection" + }, + { + "SQL": "select a from t where c_str like '_abc'", + "Best": "IndexReader(Index(t.c_d_e_str)[[NULL,+inf]]->Sel([like(test.t.c_str, _abc, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc%'", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abd\")]->Sel([like(test.t.c_str, abc%, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc_'", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abd\")]->Sel([like(test.t.c_str, abc_, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc%af'", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc\",\"abd\")]->Sel([like(test.t.c_str, abc%af, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc\\_' escape ''", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]]->Sel([like(test.t.c_str, abc\\_, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc\\_'", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]]->Sel([like(test.t.c_str, abc\\_, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc\\\\_'", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc_\"]]->Sel([like(test.t.c_str, abc\\_, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc\\_%'", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")]->Sel([like(test.t.c_str, abc\\_%, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc=_%' escape '='", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")]->Sel([like(test.t.c_str, abc=_%, 61)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 'abc\\__'", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"abc_\",\"abc`\")]->Sel([like(test.t.c_str, abc\\__, 92)]))->Projection" + }, + { + "SQL": "select a from t where c_str like 123", + "Best": "IndexReader(Index(t.c_d_e_str)[[\"123\",\"123\"]]->Sel([like(test.t.c_str, 123, 92)]))->Projection" + }, + { + "SQL": "select a from t where c = 1.9 and d > 3", + "Best": "Dual" + }, + { + "SQL": "select a from t where c < 1.1", + "Best": "IndexReader(Index(t.c_d_e)[[-inf,2)])->Projection" + }, + { + "SQL": "select a from t where c <= 1.9", + "Best": "IndexReader(Index(t.c_d_e)[[-inf,1]])->Projection" + }, + { + "SQL": "select a from t where c >= 1.1", + "Best": "IndexReader(Index(t.c_d_e)[[2,+inf]])->Projection" + }, + { + "SQL": "select a from t where c > 1.9", + "Best": "IndexReader(Index(t.c_d_e)[(1,+inf]])->Projection" + }, + { + "SQL": "select a from t where c = 123456789098765432101234", + "Best": "Dual" + }, + { + "SQL": "select a from t where c = 'hanfei'", + "Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Sel([eq(cast(test.t.c, double BINARY), cast(hanfei, double BINARY))]))->Projection" + } + ] + }, + { + "Name": "TestAggEliminator", + "Cases": [ + { + "SQL": "select max(a) from t;", + "Best": "TableReader(Table(t)->Limit)->Limit->StreamAgg" + }, + { + "SQL": "select min(a) from t;", + "Best": "TableReader(Table(t)->Limit)->Limit->StreamAgg" + }, + { + "SQL": "select min(c_str) from t;", + "Best": "IndexReader(Index(t.c_d_e_str)[[-inf,+inf]]->Limit)->Limit->StreamAgg" + }, + { + "SQL": "select max(a), b from t;", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg" + }, + { + "SQL": "select max(a+1) from t;", + "Best": "IndexReader(Index(t.f)[[NULL,+inf]]->TopN([plus(test.t.a, 1) true],0,1))->Projection->TopN([Column#40 true],0,1)->Projection->Projection->StreamAgg" + }, + { + "SQL": "select max(a), min(a) from t;", + "Best": "RightHashJoin{TableReader(Table(t)->Limit)->Limit->StreamAgg->TableReader(Table(t)->Limit)->Limit->StreamAgg}" + }, + { + "SQL": "select max(a), min(a) from t where a > 10", + "Best": "RightHashJoin{TableReader(Table(t)->Limit)->Limit->StreamAgg->TableReader(Table(t)->Limit)->Limit->StreamAgg}" + }, + { + "SQL": "select max(d), min(d) from t where c = 1 and d > 10", + "Best": "LeftHashJoin{IndexReader(Index(t.c_d_e)[(1 10,1 +inf]]->Limit)->Limit->StreamAgg->IndexReader(Index(t.c_d_e)[(1 10,1 +inf]]->Limit)->Limit->StreamAgg}" + }, + { + "SQL": "select max(a), max(c), min(f) from t", + "Best": "LeftHashJoin{RightHashJoin{TableReader(Table(t)->Limit)->Limit->StreamAgg->IndexReader(Index(t.c_d_e)[[NULL,+inf]]->Limit)->Limit->StreamAgg}->IndexReader(Index(t.f)[[NULL,+inf]]->Limit)->Limit->StreamAgg}" + }, + { + "SQL": "select max(a), max(b) from t", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg" + }, + { + "SQL": "select max(a), max(c) from t where c > 10", + "Best": "IndexReader(Index(t.c_d_e)[(10,+inf]]->HashAgg)->HashAgg" + }, + { + "SQL": "select max(a), min(a) from t where a * 3 + 10 < 100", + "Best": "IndexReader(Index(t.f)[[NULL,+inf]]->Sel([lt(plus(mul(test.t.a, 3), 10), 100)])->HashAgg)->HashAgg" + }, + { + "SQL": "select max(a) from t group by b;", + "Best": "TableReader(Table(t)->HashAgg)->HashAgg" + }, + { + "SQL": "select max(a) from (select t1.a from t t1 join t t2 on t1.a=t2.a) t", + "Best": "MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Limit->StreamAgg" + } + ] + }, + { + "Name": "TestRuleColumnPruningLogicalApply", + "Cases": [ + { + "SQL": "SELECT COUNT(*) FROM (SELECT a, (SELECT t2.b FROM t t2, t t3 WHERE t2.a = t3.a AND t1.a = t2.a LIMIT 1) t FROM t t1) t", + "Best": "IndexReader(Index(t.f)[[NULL,+inf]]->HashAgg)->HashAgg" + }, + { + "SQL": "SELECT COUNT(a) FROM (SELECT a, (SELECT t2.b FROM t t2, t t3 WHERE t2.a = t3.a AND t1.a = t2.a LIMIT 1) t FROM t t1) t", + "Best": "IndexReader(Index(t.f)[[NULL,+inf]]->HashAgg)->HashAgg" + }, + { + "SQL": "SELECT COUNT(t) FROM (SELECT a, (SELECT t2.b FROM t t2, t t3 WHERE t2.a = t3.a AND t1.a = t2.a LIMIT 1) t FROM t t1) t", + "Best": "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->Limit}->HashAgg" + }, + { + "SQL": "SELECT COUNT(a) FROM t t1 WHERE t1.a IN (SELECT t2.a FROM t t2, t t3 WHERE t2.b = t3.b)", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.b,test.t.b)->HashAgg}(test.t.a,test.t.a)->HashAgg" + }, + { + "SQL": "SELECT a FROM (SELECT a, (SELECT t2.b FROM t t2, t t3 WHERE t2.a = t3.a AND t1.a = t2.a LIMIT 1) t FROM t t1) t", + "Best": "IndexReader(Index(t.f)[[NULL,+inf]])" + }, + { + "SQL": "SELECT a FROM t WHERE b IN (SELECT t2.b FROM t t2, t t3 WHERE t2.a = t3.a)", + "Best": "LeftHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->HashAgg}(test.t.b,test.t.b)" + }, + { + "SQL": "SELECT a FROM t WHERE EXISTS (SELECT t2.b FROM t t2, t t3 WHERE t2.a = t3.a AND t2.b=t.b)", + "Best": "LeftHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)}(test.t.b,test.t.b)" + }, + { + "SQL": "SELECT a FROM t WHERE NOT EXISTS (SELECT t2.b FROM t t2, t t3 WHERE t2.a = t3.a AND t2.b=t.b)", + "Best": "LeftHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)}(test.t.b,test.t.b)" + }, + { + "SQL": "SELECT a FROM t WHERE b IN (SELECT b FROM t WHERE b = 1 AND a IN (SELECT a FROM t WHERE a > 0))", + "Best": "RightHashJoin{IndexJoin{TableReader(Table(t)->Sel([eq(test.t.b, 1)]))->TableReader(Table(t)->Sel([gt(test.t.a, 0)]))}(test.t.a,test.t.a)->HashAgg->TableReader(Table(t))}(test.t.b,test.t.b)" + }, + { + "SQL": "SELECT a FROM t WHERE b IN (SELECT b FROM t WHERE b = 1 AND a IN (SELECT t2.a FROM (SELECT t1.a, (SELECT t2.b FROM t t2, t t3 WHERE t2.a = t3.a AND t1.a = t2.a LIMIT 1) t FROM t t1) t2))", + "Best": "LeftHashJoin{TableReader(Table(t))->IndexJoin{TableReader(Table(t)->Sel([eq(test.t.b, 1)]))->TableReader(Table(t))}(test.t.a,test.t.a)->HashAgg}(test.t.b,test.t.b)" + } + ] + }, + { + "Name": "TestUnmatchedTableInHint", + "Cases": [ + { + "SQL": "SELECT /*+ TIDB_SMJ(t3, t4) */ * from t t1, t t2 where t1.a = t2.a", + "Warning": "[planner:1815]There are no matching table names for (t3, t4) in optimizer hint /*+ MERGE_JOIN(t3, t4) */ or /*+ TIDB_SMJ(t3, t4) */. Maybe you can use the table alias name" + }, + { + "SQL": "SELECT /*+ TIDB_HJ(t3, t4) */ * from t t1, t t2 where t1.a = t2.a", + "Warning": "[planner:1815]There are no matching table names for (t3, t4) in optimizer hint /*+ HASH_JOIN(t3, t4) */ or /*+ TIDB_HJ(t3, t4) */. Maybe you can use the table alias name" + }, + { + "SQL": "SELECT /*+ TIDB_INLJ(t3, t4) */ * from t t1, t t2 where t1.a = t2.a", + "Warning": "[planner:1815]There are no matching table names for (t3, t4) in optimizer hint /*+ INL_JOIN(t3, t4) */ or /*+ TIDB_INLJ(t3, t4) */. Maybe you can use the table alias name" + }, + { + "SQL": "SELECT /*+ TIDB_SMJ(t1, t2) */ * from t t1, t t2 where t1.a = t2.a", + "Warning": "" + }, + { + "SQL": "SELECT /*+ TIDB_SMJ(t3, t4) */ * from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a", + "Warning": "[planner:1815]There are no matching table names for (t4) in optimizer hint /*+ MERGE_JOIN(t3, t4) */ or /*+ TIDB_SMJ(t3, t4) */. Maybe you can use the table alias name" + } + ] + }, + { + "Name": "TestJoinHints", + "Cases": [ + { + "SQL": "select /*+ TIDB_INLJ(t1) */ t1.a, t2.a, t3.a from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a;", + "Best": "MergeInnerJoin{IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)", + "Warning": "", + "Hints": "merge_join(@`sel_1` `test`.`t3`), inl_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` ), no_order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_1` `test`.`t2` ), order_index(@`sel_1` `test`.`t2` `primary`), use_index(@`sel_1` `test`.`t3` ), order_index(@`sel_1` `test`.`t3` `primary`)" + }, + { + "SQL": "select /*+ TIDB_INLJ(test.t1) */ t1.a, t2.a, t3.a from t t1, t t2, t t3 where t1.a = t2.a and t2.a = t3.a;", + "Best": "MergeInnerJoin{IndexJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->TableReader(Table(t))}(test.t.a,test.t.a)", + "Warning": "", + "Hints": "merge_join(@`sel_1` `test`.`t3`), inl_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` ), no_order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_1` `test`.`t2` ), order_index(@`sel_1` `test`.`t2` `primary`), use_index(@`sel_1` `test`.`t3` ), order_index(@`sel_1` `test`.`t3` `primary`)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t1) */ t1.b, t2.a from t t1, t t2 where t1.b = t2.a;", + "Best": "LeftHashJoin{TableReader(Table(t))->IndexReader(Index(t.f)[[NULL,+inf]])}(test.t.b,test.t.a)", + "Warning": "[planner:1815]Optimizer Hint /*+ INL_JOIN(t1) */ or /*+ TIDB_INLJ(t1) */ is inapplicable", + "Hints": "hash_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` ), no_order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_1` `test`.`t2` `f`), no_order_index(@`sel_1` `test`.`t2` `f`)" + }, + { + "SQL": "select /*+ TIDB_INLJ(t2) */ t1.b, t2.a from t2 t1, t2 t2 where t1.b=t2.b and t2.c=-1;", + "Best": "IndexJoin{TableReader(Table(t2)->Sel([eq(test.t2.c, -1)]))->IndexReader(Index(t2.b)[[NULL,NULL]])}(test.t2.b,test.t2.b)->Projection", + "Warning": "[planner:1815]Optimizer Hint /*+ INL_JOIN(t2) */ or /*+ TIDB_INLJ(t2) */ is inapplicable", + "Hints": "inl_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t2` ), no_order_index(@`sel_1` `test`.`t2` `primary`), use_index(@`sel_1` `test`.`t1` `b`), no_order_index(@`sel_1` `test`.`t1` `b`)" + } + ] + }, + { + "Name": "TestAggregationHints", + "Cases": [ + { + "SQL": "select count(*) from t t1, t t2 where t1.a = t2.b", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->StreamAgg", + "Warning": "" + }, + { + "SQL": "select count(t1.a) from t t1, t t2 where t1.a = t2.a*2 group by t1.a", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]])->Projection}(test.t.a,Column#26)->HashAgg", + "Warning": "" + }, + { + "SQL": "select /*+ HASH_AGG() */ count(*) from t t1, t t2 where t1.a = t2.b", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->HashAgg", + "Warning": "" + }, + { + "SQL": "select /*+ STREAM_AGG() */ count(t1.a) from t t1, t t2 where t1.a = t2.a*2 group by t1.a", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]])->Projection}(test.t.a,Column#26)->Sort->StreamAgg", + "Warning": "" + }, + { + "SQL": "select /*+ HASH_AGG() STREAM_AGG() */ count(*) from t t1, t t2 where t1.a = t2.b", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(test.t.a,test.t.b)->StreamAgg", + "Warning": "[planner:1815]Optimizer aggregation hints are conflicted" + }, + { + "SQL": "select /*+ STREAM_AGG() */ distinct a from t", + "Best": "IndexReader(Index(t.f)[[NULL,+inf]])", + "Warning": "" + }, + { + "SQL": "select /*+ HASH_AGG() */ t1.a from t t1 where t1.a < any(select t2.b from t t2)", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t)->HashAgg)->HashAgg->Sel([ne(Column#27, 0)])}", + "Warning": "" + }, + { + "SQL": "select /*+ hash_agg() */ t1.a from t t1 where t1.a != any(select t2.b from t t2)", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))->HashAgg->Sel([ne(Column#28, 0)])}", + "Warning": "" + }, + { + "SQL": "select /*+ hash_agg() */ t1.a from t t1 where t1.a = all(select t2.b from t t2)", + "Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))->HashAgg->Sel([or(and(le(Column#26, 1), if(ne(Column#27, 0), , 1)), or(eq(Column#28, 0), 0))])}", + "Warning": "" + }, + { + "SQL": "select /*+ STREAM_AGG() */ sum(t1.a) from t t1 join t t2 on t1.b = t2.b group by t1.b", + "Best": "LeftHashJoin{TableReader(Table(t))->TableReader(Table(t))->Sort->Projection->StreamAgg}(test.t.b,test.t.b)->HashAgg", + "Warning": "" + }, + { + "SQL": "select /*+ STREAM_AGG() */ e, sum(b) from t group by e", + "Best": "TableReader(Table(t))->Sort->Projection->StreamAgg->Projection", + "Warning": "" + } + ] + }, + { + "Name": "TestQueryBlockHint", + "Cases": [ + { + "SQL": "select /*+ MERGE_JOIN(@sel_1 t1), INL_JOIN(@sel_2 t3) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Plan": "IndexJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)", + "Hints": "use_index(@`sel_1` `test`.`t1` ), order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_2` `test`.`t2` ), order_index(@`sel_2` `test`.`t2` `primary`), use_index(@`sel_2` `test`.`t3` `c_d_e`), no_order_index(@`sel_2` `test`.`t3` `c_d_e`)" + }, + { + "SQL": "select /*+ MERGE_JOIN(@sel_1 t1), INL_JOIN(@qb t3) */ t1.a, t1.b from t t1, (select /*+ QB_NAME(qb) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Plan": "IndexJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->IndexReader(Index(t.c_d_e)[[NULL,NULL]])}(test.t.a,test.t.c)", + "Hints": "use_index(@`sel_1` `test`.`t1` ), order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_2` `test`.`t2` ), order_index(@`sel_2` `test`.`t2` `primary`), use_index(@`sel_2` `test`.`t3` `c_d_e`), no_order_index(@`sel_2` `test`.`t3` `c_d_e`)" + }, + { + "SQL": "select /*+ HASH_JOIN(@sel_1 t1), MERGE_JOIN(@sel_2 t2) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Plan": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)", + "Hints": "use_index(@`sel_1` `test`.`t1` ), order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_2` `test`.`t2` ), order_index(@`sel_2` `test`.`t2` `primary`), use_index(@`sel_2` `test`.`t3` `c_d_e`), order_index(@`sel_2` `test`.`t3` `c_d_e`)" + }, + { + "SQL": "select /*+ HASH_JOIN(@sel_1 t1), MERGE_JOIN(@qb t2) */ t1.a, t1.b from t t1, (select /*+ QB_NAME(qb) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Plan": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)", + "Hints": "use_index(@`sel_1` `test`.`t1` ), order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_2` `test`.`t2` ), order_index(@`sel_2` `test`.`t2` `primary`), use_index(@`sel_2` `test`.`t3` `c_d_e`), order_index(@`sel_2` `test`.`t3` `c_d_e`)" + }, + { + "SQL": "select /*+ INL_JOIN(@sel_1 t1), HASH_JOIN(@sel_2 t2) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Plan": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)", + "Hints": "use_index(@`sel_1` `test`.`t1` ), order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_2` `test`.`t2` ), order_index(@`sel_2` `test`.`t2` `primary`), use_index(@`sel_2` `test`.`t3` `c_d_e`), order_index(@`sel_2` `test`.`t3` `c_d_e`)" + }, + { + "SQL": "select /*+ INL_JOIN(@sel_1 t1), HASH_JOIN(@qb t2) */ t1.a, t1.b from t t1, (select /*+ QB_NAME(qb) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a", + "Plan": "MergeInnerJoin{MergeInnerJoin{TableReader(Table(t))->TableReader(Table(t))}(test.t.a,test.t.a)->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(test.t.a,test.t.c)", + "Hints": "use_index(@`sel_1` `test`.`t1` ), order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_2` `test`.`t2` ), order_index(@`sel_2` `test`.`t2` `primary`), use_index(@`sel_2` `test`.`t3` `c_d_e`), order_index(@`sel_2` `test`.`t3` `c_d_e`)" + }, + { + "SQL": "select /*+ HASH_AGG(@sel_1), STREAM_AGG(@sel_2) */ count(*) from t t1 where t1.a < (select count(*) from t t2 where t1.a > t2.a)", + "Plan": "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]]->Sel([gt(test.t.a, test.t.a)])->StreamAgg)->StreamAgg}->HashAgg", + "Hints": "hash_agg(@`sel_1`), use_index(@`sel_1` `test`.`t1` `f`), no_order_index(@`sel_1` `test`.`t1` `f`), stream_agg(@`sel_2`), use_index(@`sel_2` `test`.`t2` `f`), no_order_index(@`sel_2` `test`.`t2` `f`), agg_to_cop(@`sel_2`)" + }, + { + "SQL": "select /*+ STREAM_AGG(@sel_1), HASH_AGG(@qb) */ count(*) from t t1 where t1.a < (select /*+ QB_NAME(qb) */ count(*) from t t2 where t1.a > t2.a)", + "Plan": "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.f)[[NULL,+inf]]->Sel([gt(test.t.a, test.t.a)])->HashAgg)->HashAgg}->StreamAgg", + "Hints": "stream_agg(@`sel_1`), use_index(@`sel_1` `test`.`t1` `f`), no_order_index(@`sel_1` `test`.`t1` `f`), hash_agg(@`sel_2`), use_index(@`sel_2` `test`.`t2` `f`), no_order_index(@`sel_2` `test`.`t2` `f`), agg_to_cop(@`sel_2`)" + }, + { + "SQL": "select /*+ HASH_AGG(@sel_2) */ a, (select count(*) from t t1 where t1.b > t.a) from t where b > (select b from t t2 where t2.b = t.a limit 1)", + "Plan": "Apply{Apply{TableReader(Table(t))->TableReader(Table(t)->Sel([eq(test.t.b, test.t.a)])->Limit)->Limit}->TableReader(Table(t)->Sel([gt(test.t.b, test.t.a)])->HashAgg)->HashAgg}->Projection", + "Hints": "use_index(@`sel_1` `test`.`t` ), no_order_index(@`sel_1` `test`.`t` `primary`), use_index(@`sel_3` `test`.`t2` ), no_order_index(@`sel_3` `test`.`t2` `primary`), limit_to_cop(@`sel_3`), hash_agg(@`sel_2`), use_index(@`sel_2` `test`.`t1` ), no_order_index(@`sel_2` `test`.`t1` `primary`), agg_to_cop(@`sel_2`)" + }, + { + "SQL": "select /*+ HASH_JOIN(@sel_1 t1), HASH_JOIN(@sel_2 t1) */ t1.b, t2.a, t2.aa from t t1, (select t1.a as a, t2.a as aa from t t1, t t2) t2 where t1.a = t2.aa;", + "Plan": "LeftHashJoin{LeftHashJoin{TableReader(Table(t))->IndexReader(Index(t.f)[[NULL,+inf]])}(test.t.a,test.t.a)->IndexReader(Index(t.f)[[NULL,+inf]])}->Projection", + "Hints": "use_index(@`sel_1` `test`.`t1` ), no_order_index(@`sel_1` `test`.`t1` `primary`), use_index(@`sel_2` `test`.`t2` `f`), no_order_index(@`sel_2` `test`.`t2` `f`), use_index(@`sel_2` `test`.`t1` `f`), no_order_index(@`sel_2` `test`.`t1` `f`)" + }, + { + "SQL": "select /*+ HASH_JOIN(@sel_2 t1@sel_2, t2@sel_2), MERGE_JOIN(@sel_1 t1@sel_1, t2@sel_1) */ * from (select t1.a, t1.b from t t1, t t2 where t1.a = t2.a) t1, t t2 where t1.b = t2.b", + "Plan": "MergeInnerJoin{TableReader(Table(t))->Sort->LeftHashJoin{TableReader(Table(t))->IndexReader(Index(t.f)[[NULL,+inf]])}(test.t.a,test.t.a)->Sort}(test.t.b,test.t.b)->Projection", + "Hints": "use_index(@`sel_1` `test`.`t2` ), no_order_index(@`sel_1` `test`.`t2` `primary`), hash_join(@`sel_2` `test`.`t1`), use_index(@`sel_2` `test`.`t1` ), no_order_index(@`sel_2` `test`.`t1` `primary`), use_index(@`sel_2` `test`.`t2` `f`), no_order_index(@`sel_2` `test`.`t2` `f`)" + } + ] + }, + { + "Name": "TestSemiJoinToInner", + "Cases": [ + { + "SQL": "select t1.a, (select count(t2.a) from t t2 where t2.g in (select t3.d from t t3 where t3.c = t1.a)) as agg_col from t t1;", + "Best": "Apply{IndexReader(Index(t.f)[[NULL,+inf]])->IndexHashJoin{IndexReader(Index(t.c_d_e)[[NULL,+inf]]->HashAgg)->HashAgg->IndexReader(Index(t.g)[[NULL,NULL]])}(test.t.d,test.t.g)}->HashAgg" + } + ] + }, + { + "Name": "TestIndexJoinHint", + "Cases": [ + { + "SQL": "select /*+ INL_JOIN(t1) */ * from t1 join t2 on t1.a = t2.a;", + "Plan": "IndexJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)" + }, + { + "SQL": "select /*+ INL_HASH_JOIN(t1) */ * from t1 join t2 on t1.a = t2.a;", + "Plan": "IndexHashJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)" + }, + { + "SQL": "select /*+ INL_MERGE_JOIN(t1) */ * from t1 join t2 on t1.a = t2.a;", + "Plan": "IndexMergeJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->Projection->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)" + }, + { + "SQL": "select /*+ inl_merge_join(t2) */ t1.a, t2.a from t t1 left join t t2 use index(g_2) on t1.g=t2.g", + "Plan": "IndexMergeJoin{IndexReader(Index(t.g_2)[[NULL,+inf]])->IndexReader(Index(t.g_2)[[NULL,NULL]]->Sel([not(isnull(test.t.g))]))}(test.t.g,test.t.g)" + }, + { + "SQL": "select /*+inl_merge_join(t2)*/ t1.a, t2.a from t t1 left join t t2 use index(g_2) on t1.g=t2.g order by t1.a", + "Plan": "IndexMergeJoin{IndexReader(Index(t.g_2)[[NULL,+inf]])->IndexReader(Index(t.g_2)[[NULL,NULL]]->Sel([not(isnull(test.t.g))]))}(test.t.g,test.t.g)->Sort" + } + ] + }, + { + "Name": "TestAggToCopHint", + "Cases": [ + { + "SQL": "select /*+ AGG_TO_COP(), HASH_AGG(), USE_INDEX(t) */ sum(a) from ta group by a", + "Best": "IndexReader(Index(ta.a)[[NULL,+inf]]->HashAgg)->HashAgg", + "Warning": "[planner:1815]use_index(test.t) is inapplicable, check whether the table(test.t) exists" + }, + { + "SQL": "select /*+ AGG_TO_COP(), USE_INDEX(t) */ sum(b) from ta group by b", + "Best": "TableReader(Table(ta)->HashAgg)->HashAgg", + "Warning": "[planner:1815]use_index(test.t) is inapplicable, check whether the table(test.t) exists" + }, + { + "SQL": "select /*+ AGG_TO_COP(), HASH_AGG(), USE_INDEX(t) */ distinct a from ta group by a", + "Best": "IndexReader(Index(ta.a)[[NULL,+inf]]->HashAgg)->HashAgg", + "Warning": "[planner:1815]use_index(test.t) is inapplicable, check whether the table(test.t) exists" + }, + { + "SQL": "select /*+ AGG_TO_COP(), HASH_AGG(), HASH_JOIN(t1), USE_INDEX(t1), USE_INDEX(t2) */ sum(t1.a) from ta t1, ta t2 where t1.a = t2.b group by t1.a", + "Best": "LeftHashJoin{TableReader(Table(ta)->Sel([not(isnull(test.ta.a))]))->TableReader(Table(ta)->Sel([not(isnull(test.ta.b))]))}(test.ta.a,test.ta.b)->Projection->HashAgg", + "Warning": "[planner:1815]Optimizer Hint AGG_TO_COP is inapplicable" + } + ] + }, + { + "Name": "TestGroupConcatOrderby", + "Cases": [ + { + "SQL": "select /*+ agg_to_cop */ group_concat(name ORDER BY name desc SEPARATOR '++'), group_concat(id ORDER BY name desc, id asc SEPARATOR '--') from test;", + "Plan": [ + "HashAgg 1.00 root funcs:group_concat(Column#6 order by Column#7 desc separator \"++\")->Column#4, funcs:group_concat(Column#8 order by Column#9 desc, Column#10 separator \"--\")->Column#5", + "└─Projection 10000.00 root cast(test.test.name, var_string(20))->Column#6, test.test.name->Column#7, cast(test.test.id, var_string(20))->Column#8, test.test.name->Column#9, test.test.id->Column#10", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo" + ], + "Result": [ + "500++200++30++20++20++10 3--3--1--1--2--1" + ] + }, + { + "SQL": "select /*+ agg_to_cop */ group_concat(name ORDER BY name desc SEPARATOR '++'), group_concat(id ORDER BY name desc, id asc SEPARATOR '--') from ptest;", + "Plan": [ + "HashAgg 1.00 root funcs:group_concat(Column#6 order by Column#7 desc separator \"++\")->Column#4, funcs:group_concat(Column#8 order by Column#9 desc, Column#10 separator \"--\")->Column#5", + "└─Projection 10000.00 root cast(test.ptest.name, var_string(20))->Column#6, test.ptest.name->Column#7, cast(test.ptest.id, var_string(20))->Column#8, test.ptest.name->Column#9, test.ptest.id->Column#10", + " └─TableReader 10000.00 root partition:all data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:ptest keep order:false, stats:pseudo" + ], + "Result": [ + "500++200++30++20++20++10 3--3--1--1--2--1" + ] + }, + { + "SQL": "select /*+ agg_to_cop */ group_concat(distinct name order by name desc) from test;", + "Plan": [ + "HashAgg 1.00 root funcs:group_concat(distinct Column#5 order by Column#6 desc separator \",\")->Column#4", + "└─Projection 10000.00 root cast(test.test.name, var_string(20))->Column#5, test.test.name->Column#6", + " └─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo" + ], + "Result": [ + "500,200,30,20,10" + ] + }, + { + "SQL": "select /*+ agg_to_cop */ group_concat(distinct name order by name desc) from ptest;", + "Plan": [ + "HashAgg 1.00 root funcs:group_concat(distinct Column#5 order by Column#6 desc separator \",\")->Column#4", + "└─Projection 10000.00 root cast(test.ptest.name, var_string(20))->Column#5, test.ptest.name->Column#6", + " └─TableReader 10000.00 root partition:all data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:ptest keep order:false, stats:pseudo" + ], + "Result": [ + "500,200,30,20,10" + ] + } + ] + }, + { + "Name": "TestInlineProjection", + "Cases": [ + { + "SQL": "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1, t2 where t1.a = t2.a;", + "Plan": "LeftHashJoin{TableReader(Table(t1)->Sel([not(isnull(test.t1.a))]))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t1.a,test.t2.a)", + "Hints": "hash_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` )" + }, + { + "SQL": "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;", + "Plan": "LeftHashJoin{TableReader(Table(t1)->Sel([not(isnull(test.t1.a))]))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t1.a,test.t2.a)", + "Hints": "hash_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` )" + }, + { + "SQL": "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1 left outer join t2 on t1.a = t2.a;", + "Plan": "LeftHashJoin{TableReader(Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t1.a,test.t2.a)", + "Hints": "hash_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` )" + }, + { + "SQL": "select /*+ HASH_JOIN(t1) */ t1.b, t2.b from t1 right outer join t2 on t1.a = t2.a;", + "Plan": "RightHashJoin{TableReader(Table(t1)->Sel([not(isnull(test.t1.a))]))->TableReader(Table(t2))}(test.t1.a,test.t2.a)", + "Hints": "hash_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` )" + }, + { + "SQL": "select 1 from (select /*+ HASH_JOIN(t1) */ t1.a in (select t2.a from t2) from t1) x;", + "Plan": "LeftHashJoin{IndexReader(Index(t1.idx_a)[[NULL,+inf]])->IndexReader(Index(t2.idx_a)[[NULL,+inf]])}->Projection", + "Hints": "hash_join(@`sel_2` `test`.`t1`), use_index(@`sel_2` `test`.`t1` `idx_a`), no_order_index(@`sel_2` `test`.`t1` `idx_a`), use_index(@`sel_3` `test`.`t2` `idx_a`), no_order_index(@`sel_3` `test`.`t2` `idx_a`)" + }, + { + "SQL": "select 1 from (select /*+ HASH_JOIN(t1) */ t1.a not in (select t2.a from t2) from t1) x;", + "Plan": "LeftHashJoin{IndexReader(Index(t1.idx_a)[[NULL,+inf]])->IndexReader(Index(t2.idx_a)[[NULL,+inf]])}->Projection", + "Hints": "hash_join(@`sel_2` `test`.`t1`), use_index(@`sel_2` `test`.`t1` `idx_a`), no_order_index(@`sel_2` `test`.`t1` `idx_a`), use_index(@`sel_3` `test`.`t2` `idx_a`), no_order_index(@`sel_3` `test`.`t2` `idx_a`)" + }, + { + "SQL": "select /*+ INL_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;", + "Plan": "IndexJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)", + "Hints": "inl_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` `idx_a`), no_order_index(@`sel_1` `test`.`t1` `idx_a`), use_index(@`sel_1` `test`.`t2` )" + }, + { + "SQL": "select /*+ INL_HASH_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;", + "Plan": "IndexHashJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)", + "Hints": "inl_hash_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` `idx_a`), no_order_index(@`sel_1` `test`.`t1` `idx_a`), use_index(@`sel_1` `test`.`t2` )" + }, + { + "SQL": "select /*+ INL_MERGE_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;", + "Plan": "IndexMergeJoin{IndexLookUp(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]), Table(t1))->Projection->TableReader(Table(t2)->Sel([not(isnull(test.t2.a))]))}(test.t2.a,test.t1.a)", + "Hints": "inl_merge_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` `idx_a`), order_index(@`sel_1` `test`.`t1` `idx_a`), use_index(@`sel_1` `test`.`t2` )" + }, + { + "SQL": "select /*+ MERGE_JOIN(t1) */ t1.b, t2.b from t1 inner join t2 on t1.a = t2.a;", + "Plan": "MergeInnerJoin{IndexLookUp(Index(t1.idx_a)[[-inf,+inf]], Table(t1))->Projection->IndexLookUp(Index(t2.idx_a)[[-inf,+inf]], Table(t2))->Projection}(test.t1.a,test.t2.a)", + "Hints": "merge_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` `idx_a`), order_index(@`sel_1` `test`.`t1` `idx_a`), use_index(@`sel_1` `test`.`t2` `idx_a`), order_index(@`sel_1` `test`.`t2` `idx_a`)" + } + ] + }, + { + "Name": "TestHintFromDiffDatabase", + "Cases": [ + { + "SQL": "select /*+ inl_hash_join(test.t1) */ * from test.t2 join test.t1 on test.t2.a = test.t1.a", + "Plan": "IndexHashJoin{IndexReader(Index(t2.idx_a)[[-inf,+inf]])->IndexReader(Index(t1.idx_a)[[NULL,NULL]]->Sel([not(isnull(test.t1.a))]))}(test.t2.a,test.t1.a)" + } + ] + }, + { + "Name": "TestMPPSinglePartitionType", + "Cases": [ + { + "SQL": "select * from employee where deptid>1", + "Plan": [ + "TableReader 3333.33 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 3333.33 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection 3333.33 mpp[tiflash] gt(test.employee.deptid, 1)", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select deptid+5, empid*10 from employee where deptid>1", + "Plan": [ + "TableReader 3333.33 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 3333.33 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 3333.33 mpp[tiflash] plus(test.employee.deptid, 5)->Column#5, mul(test.employee.empid, 10)->Column#6", + " └─Selection 3333.33 mpp[tiflash] gt(test.employee.deptid, 1)", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select count(*) from employee group by deptid+1", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#5", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#12, funcs:sum(Column#13)->Column#5", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#12, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#14, funcs:count(1)->Column#13", + " └─Projection 10000.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#14", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select count(distinct deptid) a from employee", + "Plan": [ + "TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#7)->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#7", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee join employee e1 using(deptid)", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12487.50 mpp[tiflash] test.employee.deptid, test.employee.empid, test.employee.salary, test.employee.empid, test.employee.salary", + " └─Projection 12487.50 mpp[tiflash] test.employee.empid, test.employee.deptid, test.employee.salary, test.employee.empid, test.employee.salary", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, test.employee.deptid)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e1 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select count(distinct a) from (select count(distinct deptid) a from employee) x", + "Plan": [ + "TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#6", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct Column#5)->Column#6", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#8)->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#8", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b+1", + "Plan": [ + "TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#7", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#12, funcs:sum(Column#13)->Column#7", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#12, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#15, funcs:count(Column#14)->Column#13", + " └─Projection 1.00 mpp[tiflash] Column#5->Column#14, plus(Column#6, 1)->Column#15", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5, funcs:count(distinct test.employee.empid)->Column#6", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, test.employee.empid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select count(a) from (select count(distinct deptid) a, count(distinct empid) b from employee) x group by b", + "Plan": [ + "TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#7", + " └─HashAgg 1.00 mpp[tiflash] group by:Column#6, funcs:count(Column#5)->Column#7", + " └─Projection 1.00 mpp[tiflash] Column#5, Column#6", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#5, funcs:count(distinct test.employee.empid)->Column#6", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, test.employee.empid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee join (select count(distinct deptid) a, count(distinct empid) b from employee) e1", + "Plan": [ + "TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 10000.00 mpp[tiflash] CARTESIAN inner join", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 1.00 mpp[tiflash] Column#9, Column#10", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#9, funcs:count(distinct test.employee.empid)->Column#10", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, test.employee.empid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join (select count(distinct deptid) a from employee) e2 on e1.deptid = e2.a", + "Plan": [ + "TableReader 1.25 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 1.25 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 1.25 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#9)]", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 1.00 mpp[tiflash] Column#9", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#10)->Column#9", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#10", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e1 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid", + "Plan": [ + "TableReader 1.25 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 1.25 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.25 mpp[tiflash] Column#5, test.employee.empid, test.employee.deptid, test.employee.salary", + " └─HashJoin 1.25 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#5)]", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 1.00 mpp[tiflash] Column#5", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#10)->Column#5", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#10", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b", + "Plan": [ + "TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 1.00 mpp[tiflash] inner join, equal:[eq(Column#5, Column#10)]", + " ├─ExchangeReceiver(Build) 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 1.00 mpp[tiflash] Column#5", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#11)->Column#5", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#11", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Projection(Probe) 1.00 mpp[tiflash] Column#10", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#12)->Column#10", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#12", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join employee e2 on e1.deptid = e2.deptid", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, test.employee.deptid)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:e1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#6, Column#5, test.employee.empid, test.employee.deptid, test.employee.salary", + " └─HashJoin 8000.00 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#6)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#6, Column#5", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#5, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:sum(Column#14)->Column#5, funcs:firstrow(Column#15)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#13, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#27, funcs:count(Column#25)->Column#14, funcs:firstrow(Column#26)->Column#15", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid->Column#25, test.employee.deptid->Column#26, plus(test.employee.deptid, 1)->Column#27", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8000.00 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#10)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#10, Column#9", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#9, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:sum(Column#14)->Column#9, funcs:firstrow(Column#15)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#13, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#27, funcs:count(Column#25)->Column#14, funcs:firstrow(Column#26)->Column#15", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid->Column#25, test.employee.deptid->Column#26, plus(test.employee.deptid, 1)->Column#27", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Selection(Probe) 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e1 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.d = e2.d", + "Plan": [ + "TableReader 6400.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6400.00 mpp[tiflash] inner join, equal:[eq(Column#6, Column#12)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#6, Column#5", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#5, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#17, funcs:sum(Column#18)->Column#5, funcs:firstrow(Column#19)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#17, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#43, funcs:count(Column#41)->Column#18, funcs:firstrow(Column#42)->Column#19", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid->Column#41, test.employee.deptid->Column#42, plus(test.employee.deptid, 1)->Column#43", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─Projection(Probe) 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#12, Column#11", + " └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " └─Projection 8000.00 mpp[tiflash] Column#11, test.employee.deptid", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#20, funcs:sum(Column#21)->Column#11, funcs:firstrow(Column#22)->test.employee.deptid", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#20, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#46, funcs:count(Column#44)->Column#21, funcs:firstrow(Column#45)->Column#22", + " └─Projection 10000.00 mpp[tiflash] test.employee.empid->Column#44, test.employee.deptid->Column#45, plus(test.employee.deptid, 1)->Column#46", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "set tidb_broadcast_join_threshold_count=1", + "Plan": null + }, + { + "SQL": "set tidb_broadcast_join_threshold_size=1", + "Plan": null + }, + { + "SQL": "select * from (select count(distinct deptid) a from employee) e1 join employee e2 on e1.a = e2.deptid", + "Plan": [ + "Projection 1.25 root Column#5, test.employee.empid, test.employee.deptid, test.employee.salary", + "└─HashJoin 1.25 root inner join, equal:[eq(test.employee.deptid, Column#5)]", + " ├─TableReader(Build) 1.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─Projection 1.00 mpp[tiflash] Column#5", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#12)->Column#5", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#12", + " │ └─ExchangeReceiver 1.00 mpp[tiflash] ", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " │ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─TableReader(Probe) 9990.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select count(distinct deptid) a from employee) e1 join (select count(distinct deptid) b from employee) e2 on e1.a=e2.b", + "Plan": [ + "HashJoin 1.00 root inner join, equal:[eq(Column#5, Column#10)]", + "├─TableReader(Build) 1.00 root MppVersion: 2, data:ExchangeSender", + "│ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─Projection 1.00 mpp[tiflash] Column#10", + "│ └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#16)->Column#10", + "│ └─ExchangeReceiver 1.00 mpp[tiflash] ", + "│ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + "│ └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#16", + "│ └─ExchangeReceiver 1.00 mpp[tiflash] ", + "│ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + "│ └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + "│ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + "└─TableReader(Probe) 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#5", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#15)->Column#5", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct test.employee.deptid)->Column#15", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " └─HashAgg 1.00 mpp[tiflash] group by:test.employee.deptid, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join employee e2 on e1.deptid = e2.deptid", + "Plan": [ + "TableReader 12487.50 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12487.50 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 12487.50 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, test.employee.deptid)]", + " ├─ExchangeReceiver(Build) 9990.00 mpp[tiflash] ", + " │ └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " │ └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:e1 pushed down filter:empty, keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.employee.deptid, collate: binary]", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join employee e2 on e1.d = e2.deptid", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] Column#6, Column#5, test.employee.empid, test.employee.deptid, test.employee.salary", + " └─Projection 8000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, test.employee.salary, Column#6, Column#5, Column#26", + " └─HashJoin 8000.00 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#6)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#6, collate: binary]", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#6, Column#5", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#5, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:sum(Column#14)->Column#5, funcs:firstrow(Column#15)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#13, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#29, funcs:count(Column#27)->Column#14, funcs:firstrow(Column#28)->Column#15", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid->Column#27, test.employee.deptid->Column#28, plus(test.employee.deptid, 1)->Column#29", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#26, collate: binary]", + " └─Projection 9990.00 mpp[tiflash] test.employee.empid, test.employee.deptid, test.employee.salary, cast(test.employee.deptid, bigint(20))->Column#26", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e2 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, test.employee.salary, Column#10, Column#9", + " └─Projection 8000.00 mpp[tiflash] test.employee.empid, test.employee.deptid, test.employee.salary, Column#10, Column#9, Column#26", + " └─HashJoin 8000.00 mpp[tiflash] inner join, equal:[eq(test.employee.deptid, Column#10)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#10, collate: binary]", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#10, Column#9", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#9, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#13, funcs:sum(Column#14)->Column#9, funcs:firstrow(Column#15)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#13, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#29, funcs:count(Column#27)->Column#14, funcs:firstrow(Column#28)->Column#15", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid->Column#27, test.employee.deptid->Column#28, plus(test.employee.deptid, 1)->Column#29", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 9990.00 mpp[tiflash] ", + " └─ExchangeSender 9990.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#26, collate: binary]", + " └─Projection 9990.00 mpp[tiflash] test.employee.empid, test.employee.deptid, test.employee.salary, cast(test.employee.deptid, bigint(20))->Column#26", + " └─Selection 9990.00 mpp[tiflash] not(isnull(test.employee.deptid))", + " └─TableFullScan 10000.00 mpp[tiflash] table:e1 pushed down filter:empty, keep order:false, stats:pseudo" + ] + }, + { + "SQL": "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.d = e2.d", + "Plan": [ + "TableReader 6400.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6400.00 mpp[tiflash] inner join, equal:[eq(Column#6, Column#12)]", + " ├─ExchangeReceiver(Build) 6400.00 mpp[tiflash] ", + " │ └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#6, collate: binary]", + " │ └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#6, Column#5", + " │ └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " │ └─Projection 8000.00 mpp[tiflash] Column#5, test.employee.deptid", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#17, funcs:sum(Column#18)->Column#5, funcs:firstrow(Column#19)->test.employee.deptid", + " │ └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " │ └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#17, collate: binary]", + " │ └─HashAgg 8000.00 mpp[tiflash] group by:Column#43, funcs:count(Column#41)->Column#18, funcs:firstrow(Column#42)->Column#19", + " │ └─Projection 10000.00 mpp[tiflash] test.employee.empid->Column#41, test.employee.deptid->Column#42, plus(test.employee.deptid, 1)->Column#43", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo", + " └─ExchangeReceiver(Probe) 6400.00 mpp[tiflash] ", + " └─ExchangeSender 6400.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#12, collate: binary]", + " └─Projection 6400.00 mpp[tiflash] plus(test.employee.deptid, 1)->Column#12, Column#11", + " └─Selection 6400.00 mpp[tiflash] not(isnull(plus(test.employee.deptid, 1)))", + " └─Projection 8000.00 mpp[tiflash] Column#11, test.employee.deptid", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#20, funcs:sum(Column#21)->Column#11, funcs:firstrow(Column#22)->test.employee.deptid", + " └─ExchangeReceiver 8000.00 mpp[tiflash] ", + " └─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#20, collate: binary]", + " └─HashAgg 8000.00 mpp[tiflash] group by:Column#46, funcs:count(Column#44)->Column#21, funcs:firstrow(Column#45)->Column#22", + " └─Projection 10000.00 mpp[tiflash] test.employee.empid->Column#44, test.employee.deptid->Column#45, plus(test.employee.deptid, 1)->Column#46", + " └─TableFullScan 10000.00 mpp[tiflash] table:employee keep order:false, stats:pseudo" + ] + } + ] + }, + { + "Name": "TestSemiJoinRewriteHints", + "Cases": [ + { + "SQL": "select /*+ SEMI_JOIN_REWRITE() */ * from t", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause." + }, + { + "SQL": "select * from t where a > (select /*+ SEMI_JOIN_REWRITE() */ min(b) from t t1 where t1.c = t.c)", + "Plan": [ + "HashJoin 7992.00 root inner join, equal:[eq(test.t.c, test.t.c)], other cond:gt(test.t.a, Column#9)", + "├─Selection(Build) 6393.60 root not(isnull(Column#9))", + "│ └─HashAgg 7992.00 root group by:test.t.c, funcs:min(Column#10)->Column#9, funcs:firstrow(test.t.c)->test.t.c", + "│ └─TableReader 7992.00 root data:HashAgg", + "│ └─HashAgg 7992.00 cop[tikv] group by:test.t.c, funcs:min(test.t.b)->Column#10", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.c))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9980.01 root data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.c))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause." + }, + { + "SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a=t.a)", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─HashAgg(Build) 7992.00 root group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a", + "│ └─TableReader 7992.00 root data:HashAgg", + "│ └─HashAgg 7992.00 cop[tikv] group by:test.t.a, ", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "" + }, + { + "SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ t.b from t t1 where t1.a=t.a)", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─HashAgg(Build) 7992.00 root group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a", + "│ └─TableReader 7992.00 root data:HashAgg", + "│ └─HashAgg 7992.00 cop[tikv] group by:test.t.a, ", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "" + }, + { + "SQL": "select exists(select /*+ SEMI_JOIN_REWRITE() */ * from t t1 where t1.a=t.a) from t", + "Plan": [ + "HashJoin 10000.00 root left outer semi join, equal:[eq(test.t.a, test.t.a)]", + "├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "[planner:1815]SEMI_JOIN_REWRITE() is inapplicable for LeftOuterSemiJoin." + }, + { + "SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a > t.a)", + "Plan": [ + "HashJoin 7992.00 root CARTESIAN semi join, other cond:gt(test.t.a, test.t.a)", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "[planner:1815]SEMI_JOIN_REWRITE() is inapplicable for SemiJoin with left conditions or other conditions." + } + ] + }, + { + "Name": "TestHJBuildAndProbeHint4DynamicPartitionTable", + "Cases": [ + { + "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b", + "Plan": [ + "HashJoin 12475.01 root inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]", + "├─TableReader(Build) 9980.01 root partition:all data:Selection", + "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9980.01 root partition:all data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t1.a)), not(isnull(test.t1.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Result": [ + "1 1" + ], + "Warning": null + }, + { + "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b", + "Plan": [ + "HashJoin 12475.01 root inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]", + "├─TableReader(Build) 9980.01 root partition:all data:Selection", + "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t1.a)), not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9980.01 root partition:all data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Result": [ + "1 1" + ], + "Warning": null + }, + { + "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b", + "Plan": [ + "HashJoin 12475.01 root inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]", + "├─TableReader(Build) 9980.01 root partition:all data:Selection", + "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t1.a)), not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9980.01 root partition:all data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo" + ], + "Result": [ + "1 1" + ], + "Warning": null + }, + { + "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b", + "Plan": [ + "HashJoin 12475.01 root inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]", + "├─TableReader(Build) 9980.01 root partition:all data:Selection", + "│ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9980.01 root partition:all data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t1.a)), not(isnull(test.t1.b))", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo" + ], + "Result": [ + "1 1" + ], + "Warning": null + } + ] + }, + { + "Name": "TestHJBuildAndProbeHint4TiFlash", + "Cases": [ + { + "SQL": "select /*+ hash_join_build(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b", + "Plan": [ + "TableReader 12500.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12500.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12500.00 mpp[tiflash] test.t1.a, test.t2.a", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select /*+ hash_join_probe(t2) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b", + "Plan": [ + "TableReader 12500.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12500.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12500.00 mpp[tiflash] test.t1.a, test.t2.a", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select /*+ hash_join_build(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b", + "Plan": [ + "TableReader 12500.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12500.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12500.00 mpp[tiflash] test.t1.a, test.t2.a", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select /*+ hash_join_probe(t1) */ t1.a, t2.a from t1 join t2 on t1.a=t2.a and t1.b=t2.b", + "Plan": [ + "TableReader 12500.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 12500.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 12500.00 mpp[tiflash] test.t1.a, test.t2.a", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(test.t1.a, test.t2.a) eq(test.t1.b, test.t2.b)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo" + ], + "Warning": null + } + ] + }, + { + "Name": "TestCountStarForTiFlash", + "Cases": [ + { + "SQL": "select count(*) from t", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#10", + "└─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(test.t.d)->Column#12", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select count(1), count(3.1415), count(0), count(null) from t -- every count but count(null) can be rewritten", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#18)->Column#10, funcs:count(Column#19)->Column#11, funcs:count(Column#20)->Column#12, funcs:count(Column#21)->Column#13", + "└─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(test.t.d)->Column#18, funcs:count(test.t.d)->Column#19, funcs:count(test.t.d)->Column#20, funcs:count(NULL)->Column#21", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select count(*) from t where a=1", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#10", + "└─TableReader 10.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection 10.00 mpp[tiflash] eq(test.t.a, 1)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select count(*) from t_pick_row_id", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#5)->Column#3", + "└─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(test.t_pick_row_id._tidb_rowid)->Column#5", + " └─TableFullScan 10000.00 mpp[tiflash] table:t_pick_row_id keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select t.b, t.c from (select count(*) as c from t) a, t where a.c=t.a -- test recursive", + "Plan": [ + "HashJoin 1.25 root inner join, equal:[eq(test.t.a, Column#10)]", + "├─HashAgg(Build) 1.00 root funcs:count(Column#22)->Column#10", + "│ └─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + "│ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + "│ └─HashAgg 1.00 mpp[tiflash] funcs:count(test.t.d)->Column#22", + "│ └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select * from t outTable where outTable.a > (select count(*) from t inn where inn.a = outTable.b) -- shouldn't be rewritten for correlated sub query", + "Plan": [ + "Projection 10000.00 root test.t.a, test.t.b, test.t.c, test.t.d, test.t.e, test.t.f, test.t.g, test.t.h", + "└─Apply 10000.00 root CARTESIAN inner join, other cond:gt(test.t.a, Column#19)", + " ├─TableReader(Build) 10000.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:outTable keep order:false, stats:pseudo", + " └─HashAgg(Probe) 10000.00 root funcs:count(Column#21)->Column#19", + " └─TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 10000.00 mpp[tiflash] funcs:count(1)->Column#21", + " └─Selection 80000000.00 mpp[tiflash] eq(cast(test.t.a, double BINARY), cast(test.t.b, double BINARY))", + " └─TableFullScan 100000000.00 mpp[tiflash] table:inn pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select count(*) from t t1, t t2 where t1.a=t2.e -- shouldn't be rewritten when join under agg", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#22)->Column#19", + "└─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#22", + " └─Projection 12500.00 mpp[tiflash] 1->Column#21", + " └─HashJoin 12500.00 mpp[tiflash] inner join, equal:[eq(test.t.a, test.t.e)]", + " ├─ExchangeReceiver(Build) 10000.00 mpp[tiflash] ", + " │ └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: Broadcast, Compression: FAST", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:t1 keep order:false, stats:pseudo", + " └─TableFullScan(Probe) 10000.00 mpp[tiflash] table:t2 keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select count(distinct 1) from t -- shouldn't be rewritten", + "Plan": [ + "TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 1.00 mpp[tiflash] Column#10", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(distinct Column#12)->Column#10", + " └─ExchangeReceiver 1.00 mpp[tiflash] ", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough, Compression: FAST", + " └─HashAgg 1.00 mpp[tiflash] group by:1, ", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select count(1), count(a), count(b) from t -- keep count(1)", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#16)->Column#10, funcs:count(Column#17)->Column#11, funcs:count(Column#18)->Column#12", + "└─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(1)->Column#16, funcs:count(test.t.a)->Column#17, funcs:count(test.t.b)->Column#18", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select a, count(*) from t group by a -- shouldn't be rewritten", + "Plan": [ + "TableReader 8000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 8000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 8000.00 mpp[tiflash] test.t.a, Column#10", + " └─Projection 8000.00 mpp[tiflash] Column#10, test.t.a", + " └─HashAgg 8000.00 mpp[tiflash] group by:test.t.a, funcs:count(1)->Column#10, funcs:firstrow(test.t.a)->test.t.a", + " └─ExchangeReceiver 10000.00 mpp[tiflash] ", + " └─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.a, collate: binary]", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select sum(a) from t -- sum shouldn't be rewritten", + "Plan": [ + "HashAgg 1.00 root funcs:sum(Column#12)->Column#10", + "└─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#15)->Column#12", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.a, decimal(10,0) BINARY)->Column#15", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warning": null + } + ] + }, + { + "Name": "TestHashAggPushdownToTiFlashCompute", + "Cases": [ + { + "SQL": "select /*+ agg_to_cop() hash_agg() */ avg( distinct tbl_15.col_96 ) as r0 , min( tbl_15.col_92 ) as r1 , sum( distinct tbl_15.col_91 ) as r2 , max( tbl_15.col_92 ) as r3 from tbl_15 where tbl_15.col_94 != '2033-01-09' and tbl_15.col_93 > 7623.679908049186 order by r0,r1,r2,r3 limit 79 ;", + "Plan": [ + "Limit 1.00 root offset:0, count:79", + "└─Sort 1.00 root Column#11, Column#12, Column#13, Column#14", + " └─HashAgg 1.00 root funcs:avg(distinct Column#89)->Column#11, funcs:min(Column#90)->Column#12, funcs:sum(distinct Column#91)->Column#13, funcs:max(Column#92)->Column#14", + " └─Projection 7100.44 root cast(test.tbl_15.col_96, decimal(10,0) UNSIGNED BINARY)->Column#89, Column#15->Column#90, cast(test.tbl_15.col_91, decimal(3,0) UNSIGNED BINARY)->Column#91, Column#16->Column#92", + " └─PartitionUnion 7100.44 root ", + " ├─TableReader 1775.11 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 1775.11 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1775.11 mpp[tiflash] group by:test.tbl_15.col_91, test.tbl_15.col_96, funcs:firstrow(test.tbl_15.col_96)->test.tbl_15.col_96, funcs:min(Column#18)->Column#15, funcs:firstrow(test.tbl_15.col_91)->test.tbl_15.col_91, funcs:max(Column#20)->Column#16, funcs:firstrow(test.tbl_15.col_96)->test.tbl_15.col_96, funcs:firstrow(test.tbl_15.col_91)->test.tbl_15.col_91", + " │ └─ExchangeReceiver 1775.11 mpp[tiflash] ", + " │ └─ExchangeSender 1775.11 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.tbl_15.col_96, collate: binary], [name: test.tbl_15.col_91, collate: binary]", + " │ └─HashAgg 1775.11 mpp[tiflash] group by:test.tbl_15.col_91, test.tbl_15.col_96, funcs:min(test.tbl_15.col_92)->Column#18, funcs:max(test.tbl_15.col_92)->Column#20", + " │ └─Selection 2218.89 mpp[tiflash] gt(test.tbl_15.col_93, 7623.679908049186), ne(test.tbl_15.col_94, 2033-01-09 00:00:00.000000)", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:tbl_15, partition:p0 pushed down filter:empty, keep order:false, stats:pseudo", + " ├─TableReader 1775.11 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 1775.11 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1775.11 mpp[tiflash] group by:test.tbl_15.col_91, test.tbl_15.col_96, funcs:firstrow(test.tbl_15.col_96)->test.tbl_15.col_96, funcs:min(Column#30)->Column#15, funcs:firstrow(test.tbl_15.col_91)->test.tbl_15.col_91, funcs:max(Column#32)->Column#16, funcs:firstrow(test.tbl_15.col_96)->test.tbl_15.col_96, funcs:firstrow(test.tbl_15.col_91)->test.tbl_15.col_91", + " │ └─ExchangeReceiver 1775.11 mpp[tiflash] ", + " │ └─ExchangeSender 1775.11 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.tbl_15.col_96, collate: binary], [name: test.tbl_15.col_91, collate: binary]", + " │ └─HashAgg 1775.11 mpp[tiflash] group by:test.tbl_15.col_91, test.tbl_15.col_96, funcs:min(test.tbl_15.col_92)->Column#30, funcs:max(test.tbl_15.col_92)->Column#32", + " │ └─Selection 2218.89 mpp[tiflash] gt(test.tbl_15.col_93, 7623.679908049186), ne(test.tbl_15.col_94, 2033-01-09 00:00:00.000000)", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:tbl_15, partition:p1 pushed down filter:empty, keep order:false, stats:pseudo", + " ├─TableReader 1775.11 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 1775.11 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1775.11 mpp[tiflash] group by:test.tbl_15.col_91, test.tbl_15.col_96, funcs:firstrow(test.tbl_15.col_96)->test.tbl_15.col_96, funcs:min(Column#42)->Column#15, funcs:firstrow(test.tbl_15.col_91)->test.tbl_15.col_91, funcs:max(Column#44)->Column#16, funcs:firstrow(test.tbl_15.col_96)->test.tbl_15.col_96, funcs:firstrow(test.tbl_15.col_91)->test.tbl_15.col_91", + " │ └─ExchangeReceiver 1775.11 mpp[tiflash] ", + " │ └─ExchangeSender 1775.11 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.tbl_15.col_96, collate: binary], [name: test.tbl_15.col_91, collate: binary]", + " │ └─HashAgg 1775.11 mpp[tiflash] group by:test.tbl_15.col_91, test.tbl_15.col_96, funcs:min(test.tbl_15.col_92)->Column#42, funcs:max(test.tbl_15.col_92)->Column#44", + " │ └─Selection 2218.89 mpp[tiflash] gt(test.tbl_15.col_93, 7623.679908049186), ne(test.tbl_15.col_94, 2033-01-09 00:00:00.000000)", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:tbl_15, partition:p2 pushed down filter:empty, keep order:false, stats:pseudo", + " └─TableReader 1775.11 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1775.11 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1775.11 mpp[tiflash] group by:test.tbl_15.col_91, test.tbl_15.col_96, funcs:firstrow(test.tbl_15.col_96)->test.tbl_15.col_96, funcs:min(Column#54)->Column#15, funcs:firstrow(test.tbl_15.col_91)->test.tbl_15.col_91, funcs:max(Column#56)->Column#16, funcs:firstrow(test.tbl_15.col_96)->test.tbl_15.col_96, funcs:firstrow(test.tbl_15.col_91)->test.tbl_15.col_91", + " └─ExchangeReceiver 1775.11 mpp[tiflash] ", + " └─ExchangeSender 1775.11 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.tbl_15.col_96, collate: binary], [name: test.tbl_15.col_91, collate: binary]", + " └─HashAgg 1775.11 mpp[tiflash] group by:test.tbl_15.col_91, test.tbl_15.col_96, funcs:min(test.tbl_15.col_92)->Column#54, funcs:max(test.tbl_15.col_92)->Column#56", + " └─Selection 2218.89 mpp[tiflash] gt(test.tbl_15.col_93, 7623.679908049186), ne(test.tbl_15.col_94, 2033-01-09 00:00:00.000000)", + " └─TableFullScan 10000.00 mpp[tiflash] table:tbl_15, partition:p3 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select /*+ agg_to_cop() hash_agg() */ count(1) from tbl_15 ;", + "Plan": [ + "HashAgg 1.00 root funcs:count(Column#12)->Column#11", + "└─PartitionUnion 4.00 root ", + " ├─HashAgg 1.00 root funcs:count(Column#13)->Column#12", + " │ └─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(test.tbl_15.col_91)->Column#13", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:tbl_15, partition:p0 keep order:false, stats:pseudo", + " ├─HashAgg 1.00 root funcs:count(Column#14)->Column#12", + " │ └─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(test.tbl_15.col_91)->Column#14", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:tbl_15, partition:p1 keep order:false, stats:pseudo", + " ├─HashAgg 1.00 root funcs:count(Column#15)->Column#12", + " │ └─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " │ └─HashAgg 1.00 mpp[tiflash] funcs:count(test.tbl_15.col_91)->Column#15", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:tbl_15, partition:p2 keep order:false, stats:pseudo", + " └─HashAgg 1.00 root funcs:count(Column#16)->Column#12", + " └─TableReader 1.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:count(test.tbl_15.col_91)->Column#16", + " └─TableFullScan 10000.00 mpp[tiflash] table:tbl_15, partition:p3 keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select /*+ agg_to_cop() stream_agg() */ avg( tbl_16.col_100 ) as r0 from tbl_16 where tbl_16.col_100 in ( 10672141 ) or tbl_16.col_104 in ( 'yfEG1t!*b' ,'C1*bqx_qyO' ,'vQ^yUpKHr&j#~' ) group by tbl_16.col_100 order by r0 limit 20 ;", + "Plan": [ + "TopN 20.00 root Column#10, offset:0, count:20", + "└─HashAgg 63.95 root group by:test.tbl_16.col_100, funcs:avg(Column#11, Column#12)->Column#10", + " └─PartitionUnion 63.95 root ", + " ├─StreamAgg 31.98 root group by:Column#22, funcs:count(Column#19)->Column#11, funcs:sum(Column#20)->Column#12, funcs:firstrow(Column#21)->test.tbl_16.col_100", + " │ └─Projection 39.97 root test.tbl_16.col_100->Column#19, cast(test.tbl_16.col_100, decimal(8,0) UNSIGNED BINARY)->Column#20, test.tbl_16.col_100->Column#21, test.tbl_16.col_100->Column#22", + " │ └─Sort 39.97 root test.tbl_16.col_100", + " │ └─TableReader 39.97 root MppVersion: 2, data:ExchangeSender", + " │ └─ExchangeSender 39.97 mpp[tiflash] ExchangeType: PassThrough", + " │ └─Selection 39.97 mpp[tiflash] or(eq(test.tbl_16.col_100, 10672141), in(test.tbl_16.col_104, \"yfEG1t!*b\", \"C1*bqx_qyO\", \"vQ^yUpKHr&j#~\"))", + " │ └─TableFullScan 10000.00 mpp[tiflash] table:tbl_16, partition:p0 pushed down filter:empty, keep order:false, stats:pseudo", + " └─StreamAgg 31.98 root group by:Column#26, funcs:count(Column#23)->Column#11, funcs:sum(Column#24)->Column#12, funcs:firstrow(Column#25)->test.tbl_16.col_100", + " └─Projection 39.97 root test.tbl_16.col_100->Column#23, cast(test.tbl_16.col_100, decimal(8,0) UNSIGNED BINARY)->Column#24, test.tbl_16.col_100->Column#25, test.tbl_16.col_100->Column#26", + " └─Sort 39.97 root test.tbl_16.col_100", + " └─TableReader 39.97 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 39.97 mpp[tiflash] ExchangeType: PassThrough", + " └─Selection 39.97 mpp[tiflash] or(eq(test.tbl_16.col_100, 10672141), in(test.tbl_16.col_104, \"yfEG1t!*b\", \"C1*bqx_qyO\", \"vQ^yUpKHr&j#~\"))", + " └─TableFullScan 10000.00 mpp[tiflash] table:tbl_16, partition:p1 pushed down filter:empty, keep order:false, stats:pseudo" + ], + "Warning": null + } + ] + }, + { + "Name": "TestIssues49377Plan", + "Cases": [ + { + "SQL": "select 1,1,1 union all ((select * from employee where dept_id = 1) union all ( select * from employee where dept_id = 1 order by employee_id ) order by 1 );", + "Plan": [ + "Union 21.00 root ", + "├─Projection 1.00 root 1->Column#15, 1->Column#16, 1->Column#17", + "│ └─TableDual 1.00 root rows:1", + "└─Projection 20.00 root cast(Column#12, bigint(11) BINARY)->Column#15, Column#13->Column#16, cast(Column#14, bigint(11) BINARY)->Column#17", + " └─Sort 20.00 root Column#12", + " └─Union 20.00 root ", + " ├─TableReader 10.00 root data:Selection", + " │ └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + " │ └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo", + " └─Sort 10.00 root test.employee.employee_id", + " └─TableReader 10.00 root data:Selection", + " └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + " └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select 1,1,1 union all ((select * from employee where dept_id = 1) union all ( select * from employee where dept_id = 1 order by employee_id ) order by 1 limit 1);", + "Plan": [ + "Union 2.00 root ", + "├─Projection 1.00 root 1->Column#15, 1->Column#16, 1->Column#17", + "│ └─TableDual 1.00 root rows:1", + "└─Projection 1.00 root cast(Column#12, bigint(11) BINARY)->Column#15, Column#13->Column#16, cast(Column#14, bigint(11) BINARY)->Column#17", + " └─TopN 1.00 root Column#12, offset:0, count:1", + " └─Union 2.00 root ", + " ├─TopN 1.00 root test.employee.employee_id, offset:0, count:1", + " │ └─TableReader 1.00 root data:TopN", + " │ └─TopN 1.00 cop[tikv] test.employee.employee_id, offset:0, count:1", + " │ └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + " │ └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo", + " └─TopN 1.00 root test.employee.employee_id, offset:0, count:1", + " └─TableReader 1.00 root data:TopN", + " └─TopN 1.00 cop[tikv] test.employee.employee_id, offset:0, count:1", + " └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + " └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select * from employee where dept_id = 1 union all ( select * from employee where dept_id = 1 order by employee_id) union all ( select * from employee where dept_id = 1 union all ( select * from employee where dept_id = 1 order by employee_id ) limit 1);", + "Plan": [ + "Union 21.00 root ", + "├─TableReader 10.00 root data:Selection", + "│ └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + "│ └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo", + "├─Sort 10.00 root test.employee.employee_id", + "│ └─TableReader 10.00 root data:Selection", + "│ └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + "│ └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo", + "└─Limit 1.00 root offset:0, count:1", + " └─Union 1.00 root ", + " ├─Limit 1.00 root offset:0, count:1", + " │ └─TableReader 1.00 root data:Limit", + " │ └─Limit 1.00 cop[tikv] offset:0, count:1", + " │ └─Selection 1.00 cop[tikv] eq(test.employee.dept_id, 1)", + " │ └─TableFullScan 1000.00 cop[tikv] table:employee keep order:false, stats:pseudo", + " └─TopN 1.00 root test.employee.employee_id, offset:0, count:1", + " └─TableReader 1.00 root data:TopN", + " └─TopN 1.00 cop[tikv] test.employee.employee_id, offset:0, count:1", + " └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + " └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo" + ], + "Warning": null + }, + { + "SQL": "select * from employee where dept_id = 1 union all ( select * from employee where dept_id = 1 order by employee_id) union all ( select * from employee where dept_id = 1 union all ( select * from employee where dept_id = 1 order by employee_id ) order by 1 limit 1);", + "Plan": [ + "Union 21.00 root ", + "├─TableReader 10.00 root data:Selection", + "│ └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + "│ └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo", + "├─Sort 10.00 root test.employee.employee_id", + "│ └─TableReader 10.00 root data:Selection", + "│ └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + "│ └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo", + "└─TopN 1.00 root Column#17, offset:0, count:1", + " └─Union 2.00 root ", + " ├─TopN 1.00 root test.employee.employee_id, offset:0, count:1", + " │ └─TableReader 1.00 root data:TopN", + " │ └─TopN 1.00 cop[tikv] test.employee.employee_id, offset:0, count:1", + " │ └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + " │ └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo", + " └─TopN 1.00 root test.employee.employee_id, offset:0, count:1", + " └─TableReader 1.00 root data:TopN", + " └─TopN 1.00 cop[tikv] test.employee.employee_id, offset:0, count:1", + " └─Selection 10.00 cop[tikv] eq(test.employee.dept_id, 1)", + " └─TableFullScan 10000.00 cop[tikv] table:employee keep order:false, stats:pseudo" + ], + "Warning": null + } + ] + }, + { + "Name": "TestPointgetIndexChoosen", + "Cases": [ + { + "SQL": "select * from t where b=1 and c='1';", + "Plan": [ + "Point_Get 1.00 root table:t, index:ubc(b, c) " + ], + "Warning": null + }, + { + "SQL": "select * from t where b=1 and c='1' and d='1';", + "Plan": [ + "Selection 0.00 root eq(test.t.d, \"1\")", + "└─Point_Get 1.00 root table:t, index:ubc(b, c) " + ], + "Warning": null + }, + { + "SQL": "select * from t where b in (1,2,3) and c in ('1');", + "Plan": [ + "Batch_Point_Get 3.00 root table:t, index:ubc(b, c) keep order:false, desc:false" + ], + "Warning": null + } + ] + } +] diff --git a/pkg/planner/core/integration_test.go b/pkg/planner/core/integration_test.go new file mode 100644 index 0000000000000..453a9b4c0dabc --- /dev/null +++ b/pkg/planner/core/integration_test.go @@ -0,0 +1,2315 @@ +// Copyright 2019 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package core_test + +import ( + "bytes" + "fmt" + "regexp" + "strconv" + "strings" + "testing" + "time" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/pkg/config" + "github.com/pingcap/tidb/pkg/domain" + "github.com/pingcap/tidb/pkg/expression" + "github.com/pingcap/tidb/pkg/infoschema" + "github.com/pingcap/tidb/pkg/parser/auth" + "github.com/pingcap/tidb/pkg/parser/model" + "github.com/pingcap/tidb/pkg/parser/mysql" + "github.com/pingcap/tidb/pkg/planner/core" + "github.com/pingcap/tidb/pkg/sessionctx/variable" + "github.com/pingcap/tidb/pkg/table" + "github.com/pingcap/tidb/pkg/testkit" + "github.com/pingcap/tidb/pkg/util" + "github.com/stretchr/testify/require" +) + +func TestNoneAccessPathsFoundByIsolationRead(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int primary key)") + + tk.MustExec("select * from t") + + tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") + + // Don't filter mysql.SystemDB by isolation read. + tk.MustQuery("explain format = 'brief' select * from mysql.stats_meta").Check(testkit.Rows( + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:stats_meta keep order:false, stats:pseudo")) + + _, err := tk.Exec("select * from t") + require.EqualError(t, err, "[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tikv'. Please check tiflash replica.") + + tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash, tikv'") + tk.MustExec("select * from t") + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.IsolationRead.Engines = []string{"tiflash"} + }) + // Change instance config doesn't affect isolation read. + tk.MustExec("select * from t") +} + +func TestAggPushDownEngine(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 t") + tk.MustExec("create table t(a int primary key, b varchar(20))") + tk.MustExec("set @@session.tidb_allow_tiflash_cop=ON") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") + + tk.MustQuery("explain format = 'brief' select approx_count_distinct(a) from t").Check(testkit.Rows( + "StreamAgg 1.00 root funcs:approx_count_distinct(Column#5)->Column#3", + "└─TableReader 1.00 root data:StreamAgg", + " └─StreamAgg 1.00 batchCop[tiflash] funcs:approx_count_distinct(test.t.a)->Column#5", + " └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo")) + + tk.MustExec("set @@session.tidb_isolation_read_engines = 'tikv'") + + tk.MustQuery("explain format = 'brief' select approx_count_distinct(a) from t").Check(testkit.Rows( + "HashAgg 1.00 root funcs:approx_count_distinct(test.t.a)->Column#3", + "└─TableReader 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo")) +} + +func TestIssue15110And49616(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists crm_rd_150m") + tk.MustExec(`CREATE TABLE crm_rd_150m ( + product varchar(256) DEFAULT NULL, + uks varchar(16) DEFAULT NULL, + brand varchar(256) DEFAULT NULL, + cin varchar(16) DEFAULT NULL, + created_date timestamp NULL DEFAULT NULL, + quantity int(11) DEFAULT NULL, + amount decimal(11,0) DEFAULT NULL, + pl_date timestamp NULL DEFAULT NULL, + customer_first_date timestamp NULL DEFAULT NULL, + recent_date timestamp NULL DEFAULT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;`) + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "crm_rd_150m" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") + tk.MustExec("explain format = 'brief' SELECT count(*) FROM crm_rd_150m dataset_48 WHERE (CASE WHEN (month(dataset_48.customer_first_date)) <= 30 THEN '新客' ELSE NULL END) IS NOT NULL;") + + // for #49616 + tk.MustExec(`use test`) + tk.MustExec("set @@session.tidb_isolation_read_engines = 'tikv'") + tk.MustExec(`create table t1 (k int, a int)`) + tk.MustExec(`create table t2 (k int, b int, key(k))`) + tk.MustHavePlan(`select /*+ tidb_inlj(t2, t1) */ * + from t2 left join t1 on t1.k=t2.k + where a>0 or (a=0 and b>0)`, `IndexJoin`) +} + +func TestPartitionPruningForEQ(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a datetime, b int) partition by range(weekday(a)) (partition p0 values less than(10), partition p1 values less than (100))") + + is := tk.Session().GetInfoSchema().(infoschema.InfoSchema) + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + pt := tbl.(table.PartitionedTable) + query, err := expression.ParseSimpleExpr(tk.Session().GetExprCtx(), "a = '2020-01-01 00:00:00'", expression.WithTableInfo("", tbl.Meta())) + require.NoError(t, err) + dbName := model.NewCIStr(tk.Session().GetSessionVars().CurrentDB) + columns, names, err := expression.ColumnInfos2ColumnsAndNames(tk.Session().GetExprCtx(), dbName, tbl.Meta().Name, tbl.Meta().Cols(), tbl.Meta()) + require.NoError(t, err) + // Even the partition is not monotonous, EQ condition should be prune! + // select * from t where a = '2020-01-01 00:00:00' + res, err := core.PartitionPruning(tk.Session().GetPlanCtx(), pt, []expression.Expression{query}, nil, columns, names) + require.NoError(t, err) + require.Len(t, res, 1) + require.Equal(t, 0, res[0]) +} + +func TestNotReadOnlySQLOnTiFlash(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int, b varchar(20))") + tk.MustExec(`set @@tidb_isolation_read_engines = "tiflash"`) + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + err := tk.ExecToErr("select * from t for update") + require.EqualError(t, err, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or check if the query is not readonly and sql mode is strict.`) + + err = tk.ExecToErr("insert into t select * from t") + require.EqualError(t, err, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or check if the query is not readonly and sql mode is strict.`) + + tk.MustExec("prepare stmt_insert from 'insert into t select * from t where t.a = ?'") + tk.MustExec("set @a=1") + err = tk.ExecToErr("execute stmt_insert using @a") + require.EqualError(t, err, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or check if the query is not readonly and sql mode is strict.`) +} + +func TestTimeToSecPushDownToTiFlash(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a time(4))") + tk.MustExec("insert into t values('700:10:10.123456')") + tk.MustExec("insert into t values('20:20:20')") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "10000.00", "root", " MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "10000.00", "mpp[tiflash]", " ExchangeType: PassThrough"}, + {" └─Projection_4", "10000.00", "mpp[tiflash]", " time_to_sec(test.t.a)->Column#3"}, + {" └─TableFullScan_8", "10000.00", "mpp[tiflash]", "table:t", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select time_to_sec(a) from t;").Check(rows) +} + +func TestRightShiftPushDownToTiFlash(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int)") + tk.MustExec("insert into t values(2147483647, 32)") + tk.MustExec("insert into t values(12, 2)") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "rightshift(test.t.a, test.t.b)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select a >> b from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestBitColumnPushDown(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_cost_model_version=1") + tk.MustExec("create table t1(a bit(8), b int)") + tk.MustExec("create table t2(a bit(8), b int)") + tk.MustExec("insert into t1 values ('1', 1), ('2', 2), ('3', 3), ('4', 4), ('1', 1), ('2', 2), ('3', 3), ('4', 4)") + tk.MustExec("insert into t2 values ('1', 1), ('2', 2), ('3', 3), ('4', 4), ('1', 1), ('2', 2), ('3', 3), ('4', 4)") + sql := "select b from t1 where t1.b > (select min(t2.b) from t2 where t2.a < t1.a)" + tk.MustQuery(sql).Sort().Check(testkit.Rows("2", "2", "3", "3", "4", "4")) + rows := [][]any{ + {"Projection_15", "root", "test.t1.b"}, + {"└─Apply_17", "root", "CARTESIAN inner join, other cond:gt(test.t1.b, Column#7)"}, + {" ├─TableReader_20(Build)", "root", "data:Selection_19"}, + {" │ └─Selection_19", "cop[tikv]", "not(isnull(test.t1.b))"}, + {" │ └─TableFullScan_18", "cop[tikv]", "keep order:false, stats:pseudo"}, + {" └─Selection_21(Probe)", "root", "not(isnull(Column#7))"}, + {" └─StreamAgg_23", "root", "funcs:min(test.t2.b)->Column#7"}, + {" └─TopN_24", "root", "test.t2.b, offset:0, count:1"}, + {" └─TableReader_32", "root", "data:TopN_31"}, + {" └─TopN_31", "cop[tikv]", "test.t2.b, offset:0, count:1"}, + {" └─Selection_30", "cop[tikv]", "lt(test.t2.a, test.t1.a), not(isnull(test.t2.b))"}, + {" └─TableFullScan_29", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + tk.MustExec("insert t1 values ('A', 1);") + sql = "select a from t1 where ascii(a)=65" + tk.MustQuery(sql).Check(testkit.Rows("A")) + rows = [][]any{ + {"TableReader_7", "root", "data:Selection_6"}, + {"└─Selection_6", "cop[tikv]", "eq(ascii(cast(test.t1.a, var_string(1))), 65)"}, + {" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = `eq(concat(cast(test.t1.a, var_string(1)), "A"), "AA")` + sql = "select a from t1 where concat(a, 'A')='AA'" + tk.MustQuery(sql).Check(testkit.Rows("A")) + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = `eq(cast(test.t1.a, binary(1)), "A")` + sql = "select a from t1 where binary a='A'" + tk.MustQuery(sql).Check(testkit.Rows("A")) + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = `eq(cast(test.t1.a, var_string(1)), "A")` + sql = "select a from t1 where cast(a as char)='A'" + tk.MustQuery(sql).Check(testkit.Rows("A")) + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + tk.MustExec("insert into mysql.expr_pushdown_blacklist values('bit', 'tikv','');") + tk.MustExec("admin reload expr_pushdown_blacklist;") + rows = [][]any{ + {"Selection_5", "root", `eq(cast(test.t1.a, var_string(1)), "A")`}, + {"└─TableReader_7", "root", "data:TableFullScan_6"}, + {" └─TableFullScan_6", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + sql = "select a from t1 where cast(a as char)='A'" + tk.MustQuery(sql).Check(testkit.Rows("A")) + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + tk.MustExec("delete from mysql.expr_pushdown_blacklist where name='bit'") + tk.MustExec("admin reload expr_pushdown_blacklist;") + sql = "select a from t1 where ascii(a)=65" + tk.MustQuery(sql).Check(testkit.Rows("A")) + rows = [][]any{ + {"TableReader_7", "root", "data:Selection_6"}, + {"└─Selection_6", "cop[tikv]", "eq(ascii(cast(test.t1.a, var_string(1))), 65)"}, + {" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows) + + // test collation + tk.MustExec("update mysql.tidb set VARIABLE_VALUE='True' where VARIABLE_NAME='new_collation_enabled'") + tk.MustQuery("SELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME='new_collation_enabled';").Check( + testkit.Rows("True")) + tk.MustExec("create table t3 (a bit(8));") + tk.MustExec("insert into t3 values (65)") + tk.MustExec("SET NAMES utf8mb4 COLLATE utf8mb4_bin") + tk.MustQuery("select a from t3 where cast(a as char) = 'a'").Check(testkit.Rows()) + tk.MustExec("SET NAMES utf8mb4 COLLATE utf8mb4_general_ci") + tk.MustQuery("select a from t3 where cast(a as char) = 'a'").Check(testkit.Rows("A")) +} + +func TestSysdatePushDown(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id int signed, id2 int unsigned, c varchar(11), d datetime, b double, e bit(10))") + tk.MustExec("insert into t(id, id2, c, d) values (-1, 1, 'abc', '2021-12-12')") + rows := [][]any{ + {"TableReader_7", "root", "data:Selection_6"}, + {"└─Selection_6", "cop[tikv]", "gt(test.t.d, sysdate())"}, + {" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) + // assert sysdate isn't now after set global tidb_sysdate_is_now in the same session + tk.MustExec("set global tidb_sysdate_is_now='1'") + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) + + // assert sysdate is now after set global tidb_sysdate_is_now in the new session + tk = testkit.NewTestKit(t, store) + tk.MustExec("use test") + now := time.Now() + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/expression/injectNow", fmt.Sprintf(`return(%d)`, now.Unix()))) + rows[1][2] = fmt.Sprintf("gt(test.t.d, %v)", now.Format(time.DateTime)) + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) + failpoint.Disable("github.com/pingcap/tidb/pkg/expression/injectNow") + + // assert sysdate isn't now after set session tidb_sysdate_is_now false in the same session + tk.MustExec("set tidb_sysdate_is_now='0'") + rows[1][2] = "gt(test.t.d, sysdate())" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) +} + +func TestTimeScalarFunctionPushDownResult(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(col1 datetime, col2 datetime, y int(8), m int(8), d int(8)) CHARSET=utf8 COLLATE=utf8_general_ci;") + tk.MustExec("insert into t values ('2022-03-24 01:02:03.040506', '9999-12-31 23:59:59', 9999, 12, 31);") + testcases := []struct { + sql string + function string + }{ + { + sql: "select col1, hour(col1) from t where hour(col1)=hour('2022-03-24 01:02:03.040506');", + function: "hour", + }, + { + sql: "select col1, month(col1) from t where month(col1)=month('2022-03-24 01:02:03.040506');", + function: "month", + }, + { + sql: "select col1, minute(col1) from t where minute(col1)=minute('2022-03-24 01:02:03.040506');", + function: "minute", + }, + { + function: "second", + sql: "select col1, second(col1) from t where second(col1)=second('2022-03-24 01:02:03.040506');", + }, + { + function: "microsecond", + sql: "select col1, microsecond(col1) from t where microsecond(col1)=microsecond('2022-03-24 01:02:03.040506');", + }, + { + function: "dayName", + sql: "select col1, dayName(col1) from t where dayName(col1)=dayName('2022-03-24 01:02:03.040506');", + }, + { + function: "dayOfMonth", + sql: "select col1, dayOfMonth(col1) from t where dayOfMonth(col1)=dayOfMonth('2022-03-24 01:02:03.040506');", + }, + { + function: "dayOfWeek", + sql: "select col1, dayOfWeek(col1) from t where dayOfWeek(col1)=dayOfWeek('2022-03-24 01:02:03.040506');", + }, + { + function: "dayOfYear", + sql: "select col1, dayOfYear(col1) from t where dayOfYear(col1)=dayOfYear('2022-03-24 01:02:03.040506');", + }, + { + function: "Date", + sql: "select col1, Date(col1) from t where Date(col1)=Date('2022-03-24 01:02:03.040506');", + }, + { + function: "Week", + sql: "select col1, Week(col1) from t where Week(col1)=Week('2022-03-24 01:02:03.040506');", + }, + { + function: "time_to_sec", + sql: "select col1, time_to_sec (col1) from t where time_to_sec(col1)=time_to_sec('2022-03-24 01:02:03.040506');", + }, + { + function: "DateDiff", + sql: "select col1, DateDiff(col1, col2) from t where DateDiff(col1, col2)=DateDiff('2022-03-24 01:02:03.040506', '9999-12-31 23:59:59');", + }, + { + function: "MonthName", + sql: "select col1, MonthName(col1) from t where MonthName(col1)=MonthName('2022-03-24 01:02:03.040506');", + }, + { + function: "MakeDate", + sql: "select col1, MakeDate(9999, 31) from t where MakeDate(y, d)=MakeDate(9999, 31);", + }, + { + function: "MakeTime", + sql: "select col1, MakeTime(12, 12, 31) from t where MakeTime(m, m, d)=MakeTime(12, 12, 31);", + }, + } + tk.MustExec("delete from mysql.expr_pushdown_blacklist where name != 'date_add'") + tk.MustExec("admin reload expr_pushdown_blacklist;") + for _, testcase := range testcases { + r1 := tk.MustQuery(testcase.sql).Rows() + tk.MustExec(fmt.Sprintf("insert into mysql.expr_pushdown_blacklist(name) values('%s');", testcase.function)) + tk.MustExec("admin reload expr_pushdown_blacklist;") + r2 := tk.MustQuery(testcase.sql).Rows() + require.EqualValues(t, r2, r1, testcase.sql) + } + tk.MustExec("delete from mysql.expr_pushdown_blacklist where name != 'date_add'") + tk.MustExec("admin reload expr_pushdown_blacklist;") +} + +func TestNumberFunctionPushDown(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int signed, b int unsigned,c double)") + tk.MustExec("insert into t values (-1,61,4.4)") + testcases := []struct { + sql string + function string + }{ + { + sql: "select a, mod(a,2) from t where mod(-1,2)=mod(a,2);", + function: "mod", + }, + { + sql: "select b, mod(b,2) from t where mod(61,2)=mod(b,2);", + function: "mod", + }, + { + sql: "select b,unhex(b) from t where unhex(61) = unhex(b)", + function: "unhex", + }, + { + sql: "select b, oct(b) from t where oct(61) = oct(b)", + function: "oct", + }, + { + sql: "select c, sin(c) from t where sin(4.4) = sin(c)", + function: "sin", + }, + { + sql: "select c, asin(c) from t where asin(4.4) = asin(c)", + function: "asin", + }, + { + sql: "select c, cos(c) from t where cos(4.4) = cos(c)", + function: "cos", + }, + { + sql: "select c, acos(c) from t where acos(4.4) = acos(c)", + function: "acos", + }, + { + sql: "select b,atan(b) from t where atan(61)=atan(b)", + function: "atan", + }, + { + sql: "select b, atan2(b, c) from t where atan2(61,4.4)=atan2(b,c)", + function: "atan2", + }, + { + sql: "select b,cot(b) from t where cot(61)=cot(b)", + function: "cot", + }, + { + sql: "select c from t where pi() < c", + function: "pi", + }, + } + for _, testcase := range testcases { + tk.MustExec("delete from mysql.expr_pushdown_blacklist where name != 'date_add'") + tk.MustExec("admin reload expr_pushdown_blacklist;") + r1 := tk.MustQuery(testcase.sql).Rows() + tk.MustExec(fmt.Sprintf("insert into mysql.expr_pushdown_blacklist(name) values('%s');", testcase.function)) + tk.MustExec("admin reload expr_pushdown_blacklist;") + r2 := tk.MustQuery(testcase.sql).Rows() + require.EqualValues(t, r2, r1, testcase.sql) + } +} + +func TestScalarFunctionPushDown(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id int signed, id2 int unsigned, c varchar(11), d datetime, b double, e bit(10))") + tk.MustExec("insert into t(id, id2, c, d) values (-1, 1, '{\"a\":1}', '2021-12-12')") + rows := [][]any{ + {"TableReader_7", "root", "data:Selection_6"}, + {"└─Selection_6", "cop[tikv]", "right(test.t.c, 1)"}, + {" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where right(c,1);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "mod(test.t.id, test.t.id)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id, id);"). + CheckAt([]int{0, 3, 6}, rows) + rows[1][2] = "mod(test.t.id, test.t.id2)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id, id2);"). + CheckAt([]int{0, 3, 6}, rows) + rows[1][2] = "mod(test.t.id2, test.t.id)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id2, id);"). + CheckAt([]int{0, 3, 6}, rows) + rows[1][2] = "mod(test.t.id2, test.t.id2)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id2, id2);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "sin(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where sin(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "asin(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where asin(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "cos(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where cos(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "acos(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where acos(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "atan(cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where atan(id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "atan2(cast(test.t.id, double BINARY), cast(test.t.id, double BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where atan2(id,id);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "hour(cast(test.t.d, time))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where hour(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "hour(cast(test.t.d, time))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where hour(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "minute(cast(test.t.d, time))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where minute(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "second(cast(test.t.d, time))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where second(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "month(test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where month(d);"). + CheckAt([]int{0, 3, 6}, rows) + + //rows[1][2] = "dayname(test.t.d)" + //tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where dayname(d);"). + // CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "dayofmonth(test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where dayofmonth(d);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "from_days(test.t.id)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where from_days(id);"). + CheckAt([]int{0, 3, 6}, rows) + + //rows[1][2] = "last_day(test.t.d)" + //tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where last_day(d);"). + // CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "gt(4, test.t.id)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where pi() > id;"). + CheckAt([]int{0, 3, 6}, rows) + + //rows[1][2] = "truncate(test.t.id, 0)" + //tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where truncate(id,0)"). + // CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "round(test.t.b)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where round(b)"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "date(test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where date(d)"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "week(test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where week(d)"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "datediff(test.t.d, test.t.d)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where datediff(d,d)"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "gt(test.t.d, sysdate())" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "ascii(cast(test.t.e, var_string(2)))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where ascii(e);"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "eq(json_valid(test.t.c), 1)" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where json_valid(c)=1;"). + CheckAt([]int{0, 3, 6}, rows) + + rows[1][2] = "json_contains(cast(test.t.c, json BINARY), cast(\"1\", json BINARY))" + tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where json_contains(c, '1');"). + CheckAt([]int{0, 3, 6}, rows) +} + +func TestReverseUTF8PushDownToTiFlash(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a varchar(256))") + tk.MustExec("insert into t values('pingcap')") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "reverse(test.t.a)->Column#3"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + + tk.MustQuery("explain select reverse(a) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestReversePushDownToTiFlash(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a binary(32))") + tk.MustExec("insert into t values('pingcap')") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "reverse(test.t.a)->Column#3"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + + tk.MustQuery("explain select reverse(a) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestSpacePushDownToTiFlash(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a int)") + tk.MustExec("insert into t values(5)") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "space(test.t.a)->Column#3"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + + tk.MustQuery("explain select space(a) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestExplainAnalyzeDML2(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + cases := []struct { + prepare string + sql string + planRegexp string + }{ + // Test for alloc auto ID. + { + sql: "insert into t () values ()", + planRegexp: ".*prepare.*total.*, auto_id_allocator.*alloc_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*, insert.*", + }, + // Test for rebase ID. + { + sql: "insert into t (a) values (99000000000)", + planRegexp: ".*prepare.*total.*, auto_id_allocator.*rebase_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*, insert.*", + }, + // Test for alloc auto ID and rebase ID. + { + sql: "insert into t (a) values (null), (99000000000)", + planRegexp: ".*prepare.*total.*, auto_id_allocator.*alloc_cnt: 1, rebase_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*, insert.*", + }, + // Test for insert ignore. + { + sql: "insert ignore into t values (null,1), (2, 2), (99000000000, 3), (100000000000, 4)", + planRegexp: ".*prepare.*total.*, auto_id_allocator.*alloc_cnt: 1, rebase_cnt: 2, Get.*num_rpc.*total_time.*commit_txn.*count: 3, prewrite.*get_commit_ts.*commit.*write_keys.*, check_insert.*", + }, + // Test for insert on duplicate. + { + sql: "insert into t values (null,null), (1,1),(2,2) on duplicate key update a = a + 100000000000", + planRegexp: ".*prepare.*total.*, auto_id_allocator.*alloc_cnt: 1, rebase_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*count: 2, prewrite.*get_commit_ts.*commit.*write_keys.*, check_insert.*", + }, + // Test for replace with alloc ID. + { + sql: "replace into t () values ()", + planRegexp: ".*auto_id_allocator.*alloc_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*", + }, + // Test for replace with alloc ID and rebase ID. + { + sql: "replace into t (a) values (null), (99000000000)", + planRegexp: ".*auto_id_allocator.*alloc_cnt: 1, rebase_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*", + }, + // Test for update with rebase ID. + { + prepare: "insert into t values (1,1),(2,2)", + sql: "update t set a=a*100000000000", + planRegexp: ".*auto_id_allocator.*rebase_cnt: 2, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*", + }, + } + + for _, ca := range cases { + for i := 0; i < 3; i++ { + tk.MustExec("drop table if exists t") + switch i { + case 0: + tk.MustExec("create table t (a bigint auto_increment, b int, primary key (a));") + case 1: + tk.MustExec("create table t (a bigint unsigned auto_increment, b int, primary key (a));") + case 2: + if strings.Contains(ca.sql, "on duplicate key") { + continue + } + tk.MustExec("create table t (a bigint primary key auto_random(5), b int);") + tk.MustExec("set @@allow_auto_random_explicit_insert=1;") + default: + panic("should never happen") + } + if ca.prepare != "" { + tk.MustExec(ca.prepare) + } + res := tk.MustQuery("explain analyze " + ca.sql) + resBuff := bytes.NewBufferString("") + for _, row := range res.Rows() { + _, _ = fmt.Fprintf(resBuff, "%s\t", row) + } + explain := resBuff.String() + require.Regexpf(t, ca.planRegexp, explain, "idx: %v,sql: %v", i, ca.sql) + } + } + + // Test for table without auto id. + for _, ca := range cases { + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a bigint, b int);") + tk.MustExec("insert into t () values ()") + if ca.prepare != "" { + tk.MustExec(ca.prepare) + } + res := tk.MustQuery("explain analyze " + ca.sql) + resBuff := bytes.NewBufferString("") + for _, row := range res.Rows() { + _, _ = fmt.Fprintf(resBuff, "%s\t", row) + } + explain := resBuff.String() + require.NotContainsf(t, explain, "auto_id_allocator", "sql: %v, explain: %v", ca.sql, explain) + } +} + +func TestConflictReadFromStorage(t *testing.T) { + failpoint.Enable("github.com/pingcap/tidb/pkg/planner/core/forceDynamicPrune", `return(true)`) + defer failpoint.Disable("github.com/pingcap/tidb/pkg/planner/core/forceDynamicPrune") + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec(`create table t ( + a int, b int, c varchar(20), + primary key(a), key(b), key(c) + ) partition by range columns(a) ( + partition p0 values less than(6), + partition p1 values less than(11), + partition p2 values less than(16));`) + tk.MustExec(`insert into t values (1,1,"1"), (2,2,"2"), (8,8,"8"), (11,11,"11"), (15,15,"15")`) + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + tk.MustQuery(`explain select /*+ read_from_storage(tikv[t partition(p0)], tiflash[t partition(p1, p2)]) */ * from t`) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1815 Storage hints are conflict, you can only specify one storage type of table test.t")) + tk.MustQuery(`explain select /*+ read_from_storage(tikv[t], tiflash[t]) */ * from t`) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1815 Storage hints are conflict, you can only specify one storage type of table test.t")) +} + +func TestIssue29503(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.Status.RecordQPSbyDB = true + }) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int);") + require.NoError(t, tk.ExecToErr("create binding for select 1 using select 1;")) + require.NoError(t, tk.ExecToErr("create binding for select a from t using select a from t;")) + res := tk.MustQuery("show session bindings;") + require.Len(t, res.Rows(), 2) +} + +func TestIssue31202(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("create table t31202(a int primary key, b int);") + + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t31202", L: "t31202"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + tk.MustQuery("explain format = 'brief' select * from t31202;").Check(testkit.Rows( + "TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan 10000.00 mpp[tiflash] table:t31202 keep order:false, stats:pseudo")) + + tk.MustQuery("explain format = 'brief' select * from t31202 use index (primary);").Check(testkit.Rows( + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:t31202 keep order:false, stats:pseudo")) + tk.MustExec("drop table if exists t31202") +} + +func TestAggPushToCopForCachedTable(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(`create table t32157( + process_code varchar(8) NOT NULL, + ctrl_class varchar(2) NOT NULL, + ctrl_type varchar(1) NOT NULL, + oper_no varchar(12) DEFAULT NULL, + modify_date datetime DEFAULT NULL, + d_c_flag varchar(2) NOT NULL, + PRIMARY KEY (process_code,ctrl_class,d_c_flag) NONCLUSTERED);`) + tk.MustExec("insert into t32157 values ('GDEP0071', '05', '1', '10000', '2016-06-29 00:00:00', 'C')") + tk.MustExec("insert into t32157 values ('GDEP0071', '05', '0', '0000', '2016-06-01 00:00:00', 'D')") + tk.MustExec("alter table t32157 cache") + + tk.MustQuery("explain format = 'brief' select /*+AGG_TO_COP()*/ count(*) from t32157 ignore index(primary) where process_code = 'GDEP0071'").Check(testkit.Rows( + "StreamAgg 1.00 root funcs:count(1)->Column#8]\n" + + "[└─UnionScan 10.00 root eq(test.t32157.process_code, \"GDEP0071\")]\n" + + "[ └─TableReader 10.00 root data:Selection]\n" + + "[ └─Selection 10.00 cop[tikv] eq(test.t32157.process_code, \"GDEP0071\")]\n" + + "[ └─TableFullScan 10000.00 cop[tikv] table:t32157 keep order:false, stats:pseudo")) + + require.Eventually(t, func() bool { + tk.MustQuery("select /*+AGG_TO_COP()*/ count(*) from t32157 ignore index(primary) where process_code = 'GDEP0071'").Check(testkit.Rows("2")) + return tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache + }, 10*time.Second, 500*time.Millisecond) + + tk.MustExec("drop table if exists t31202") +} + +func TestTiFlashFineGrainedShuffleWithMaxTiFlashThreads(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + tk.MustExec("set @@tidb_enforce_mpp = on") + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1(c1 int, c2 int)") + tbl1, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t1", L: "t1"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl1.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + sql := "explain select row_number() over w1 from t1 window w1 as (partition by c1);" + + getStreamCountFromExplain := func(rows [][]any) (res []uint64) { + re := regexp.MustCompile("stream_count: ([0-9]+)") + for _, row := range rows { + buf := bytes.NewBufferString("") + _, _ = fmt.Fprintf(buf, "%s\n", row) + if matched := re.FindStringSubmatch(buf.String()); matched != nil { + require.Equal(t, len(matched), 2) + c, err := strconv.ParseUint(matched[1], 10, 64) + require.NoError(t, err) + res = append(res, c) + } + } + return res + } + + // tiflash_fine_grained_shuffle_stream_count should be same with tidb_max_tiflash_threads. + tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = 0") + tk.MustExec("set @@tidb_max_tiflash_threads = 10") + rows := tk.MustQuery(sql).Rows() + streamCount := getStreamCountFromExplain(rows) + // require.Equal(t, len(streamCount), 1) + require.Equal(t, uint64(10), streamCount[0]) + + // tiflash_fine_grained_shuffle_stream_count should be default value when tidb_max_tiflash_threads is -1. + tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = 0") + tk.MustExec("set @@tidb_max_tiflash_threads = -1") + rows = tk.MustQuery(sql).Rows() + streamCount = getStreamCountFromExplain(rows) + // require.Equal(t, len(streamCount), 1) + require.Equal(t, uint64(variable.DefStreamCountWhenMaxThreadsNotSet), streamCount[0]) + + // tiflash_fine_grained_shuffle_stream_count should be default value when tidb_max_tiflash_threads is 0. + tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = 0") + tk.MustExec("set @@tidb_max_tiflash_threads = 0") + rows = tk.MustQuery(sql).Rows() + streamCount = getStreamCountFromExplain(rows) + // require.Equal(t, len(streamCount), 1) + require.Equal(t, uint64(variable.DefStreamCountWhenMaxThreadsNotSet), streamCount[0]) + + // Disabled when tiflash_fine_grained_shuffle_stream_count is -1. + tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = -1") + tk.MustExec("set @@tidb_max_tiflash_threads = 10") + rows = tk.MustQuery(sql).Rows() + streamCount = getStreamCountFromExplain(rows) + require.Equal(t, len(streamCount), 0) + + // Test when tiflash_fine_grained_shuffle_stream_count is greater than 0. + tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = 16") + tk.MustExec("set @@tidb_max_tiflash_threads = 10") + rows = tk.MustQuery(sql).Rows() + streamCount = getStreamCountFromExplain(rows) + // require.Equal(t, len(streamCount), 1) + require.Equal(t, uint64(16), streamCount[0]) +} + +func TestIssue33175(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("create table t (id bigint(45) unsigned not null, c varchar(20), primary key(id));") + tk.MustExec("insert into t values (9734095886065816707, 'a'), (10353107668348738101, 'b'), (0, 'c');") + tk.MustExec("begin") + tk.MustExec("insert into t values (33, 'd');") + tk.MustQuery("select max(id) from t;").Check(testkit.Rows("10353107668348738101")) + tk.MustExec("rollback") + + tk.MustExec("alter table t cache") + for { + tk.MustQuery("select max(id) from t;").Check(testkit.Rows("10353107668348738101")) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + break + } + } + + // // With subquery, like the original issue case. + for { + tk.MustQuery("select * from t where id > (select max(id) from t where t.id > 0);").Check(testkit.Rows()) + if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache { + break + } + } + + // Test order by desc / asc. + tk.MustQuery("select id from t order by id desc;").Check(testkit.Rows( + "10353107668348738101", + "9734095886065816707", + "0")) + + tk.MustQuery("select id from t order by id asc;").Check(testkit.Rows( + "0", + "9734095886065816707", + "10353107668348738101")) + + tk.MustExec("alter table t nocache") + tk.MustExec("drop table t") + + // Cover more code that use union scan + // TableReader/IndexReader/IndexLookup + for idx, q := range []string{ + "create temporary table t (id bigint unsigned, c int default null, index(id))", + "create temporary table t (id bigint unsigned primary key)", + } { + tk.MustExec(q) + tk.MustExec("insert into t(id) values (1), (3), (9734095886065816707), (9734095886065816708)") + tk.MustQuery("select min(id) from t").Check(testkit.Rows("1")) + tk.MustQuery("select max(id) from t").Check(testkit.Rows("9734095886065816708")) + tk.MustQuery("select id from t order by id asc").Check(testkit.Rows( + "1", "3", "9734095886065816707", "9734095886065816708")) + tk.MustQuery("select id from t order by id desc").Check(testkit.Rows( + "9734095886065816708", "9734095886065816707", "3", "1")) + if idx == 0 { + tk.MustQuery("select * from t order by id asc").Check(testkit.Rows( + "1 ", + "3 ", + "9734095886065816707 ", + "9734095886065816708 ")) + tk.MustQuery("select * from t order by id desc").Check(testkit.Rows( + "9734095886065816708 ", + "9734095886065816707 ", + "3 ", + "1 ")) + } + tk.MustExec("drop table t") + } + + // More and more test + tk.MustExec("create global temporary table `tmp1` (id bigint unsigned primary key) on commit delete rows;") + tk.MustExec("begin") + tk.MustExec("insert into tmp1 values (0),(1),(2),(65536),(9734095886065816707),(9734095886065816708);") + tk.MustQuery("select * from tmp1 where id <= 65534 or (id > 65535 and id < 9734095886065816700) or id >= 9734095886065816707 order by id desc;").Check(testkit.Rows( + "9734095886065816708", "9734095886065816707", "65536", "2", "1", "0")) + + tk.MustQuery("select * from tmp1 where id <= 65534 or (id > 65535 and id < 9734095886065816700) or id >= 9734095886065816707 order by id asc;").Check(testkit.Rows( + "0", "1", "2", "65536", "9734095886065816707", "9734095886065816708")) + + tk.MustExec("create global temporary table `tmp2` (id bigint primary key) on commit delete rows;") + tk.MustExec("begin") + tk.MustExec("insert into tmp2 values(-2),(-1),(0),(1),(2);") + tk.MustQuery("select * from tmp2 where id <= -1 or id > 0 order by id desc;").Check(testkit.Rows("2", "1", "-1", "-2")) + tk.MustQuery("select * from tmp2 where id <= -1 or id > 0 order by id asc;").Check(testkit.Rows("-2", "-1", "1", "2")) +} + +func TestIssue35083(t *testing.T) { + defer func() { + variable.SetSysVar(variable.TiDBOptProjectionPushDown, variable.BoolToOnOff(config.GetGlobalConfig().Performance.ProjectionPushDown)) + }() + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.Performance.ProjectionPushDown = true + }) + variable.SetSysVar(variable.TiDBOptProjectionPushDown, variable.BoolToOnOff(config.GetGlobalConfig().Performance.ProjectionPushDown)) + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t1 (a varchar(100), b int)") + tk.MustQuery("select @@tidb_opt_projection_push_down").Check(testkit.Rows("1")) + tk.MustQuery("explain format = 'brief' select cast(a as datetime) from t1").Check(testkit.Rows( + "TableReader 10000.00 root data:Projection", + "└─Projection 10000.00 cop[tikv] cast(test.t1.a, datetime BINARY)->Column#4", + " └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo")) +} + +func TestRepeatPushDownToTiFlash(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int)") + tk.MustExec("insert into t values(2147483647, 2)") + tk.MustExec("insert into t values(12, 2)") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "repeat(cast(test.t.a, var_string(20)), test.t.b)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select repeat(a,b) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestIssue36194(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_cost_model_version=2") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + // create virtual tiflash replica. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + tk.MustQuery("explain format = 'brief' select /*+ read_from_storage(tiflash[t]) */ * from t where a + 1 > 20 limit 100;;").Check(testkit.Rows( + "Limit 100.00 root offset:0, count:100", + "└─TableReader 100.00 root MppVersion: 2, data:ExchangeSender", + " └─ExchangeSender 100.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Limit 100.00 mpp[tiflash] offset:0, count:100", + " └─Selection 100.00 mpp[tiflash] gt(plus(test.t.a, 1), 20)", + " └─TableFullScan 125.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo")) +} + +func TestGetFormatPushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("create table t(location varchar(10));") + tk.MustExec("insert into t values('USA'), ('JIS'), ('ISO'), ('EUR'), ('INTERNAL')") + tk.MustExec("set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash';") + + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + tk.MustQuery("explain format = 'brief' select GET_FORMAT(DATE, location) from t;").Check(testkit.Rows( + "TableReader 10000.00 root MppVersion: 2, data:ExchangeSender", + "└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Projection 10000.00 mpp[tiflash] get_format(DATE, test.t.location)->Column#3", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo")) +} + +func TestAggWithJsonPushDownToTiFlash(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 t") + tk.MustExec("create table t(a json);") + tk.MustExec("insert into t values(null);") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + tk.MustExec("set @@session.tidb_allow_tiflash_cop=ON") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"HashAgg_6", "root", "funcs:avg(Column#4)->Column#3"}, + {"└─Projection_19", "root", "cast(test.t.a, double BINARY)->Column#4"}, + {" └─TableReader_12", "root", "data:TableFullScan_11"}, + {" └─TableFullScan_11", "cop[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select avg(a) from t;").CheckAt([]int{0, 2, 4}, rows) + + rows = [][]any{ + {"HashAgg_6", "root", "funcs:sum(Column#4)->Column#3"}, + {"└─Projection_19", "root", "cast(test.t.a, double BINARY)->Column#4"}, + {" └─TableReader_12", "root", "data:TableFullScan_11"}, + {" └─TableFullScan_11", "cop[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select sum(a) from t;").CheckAt([]int{0, 2, 4}, rows) + + rows = [][]any{ + {"HashAgg_6", "root", "funcs:group_concat(Column#4 separator \",\")->Column#3"}, + {"└─Projection_13", "root", "cast(test.t.a, var_string(4294967295))->Column#4"}, + {" └─TableReader_10", "root", "data:TableFullScan_9"}, + {" └─TableFullScan_9", "cop[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select /*+ hash_agg() */ group_concat(a) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestLeftShiftPushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int)") + tk.MustExec("insert into t values(2147483647, 32)") + tk.MustExec("insert into t values(12, 2)") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "leftshift(test.t.a, test.t.b)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select a << b from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestHexIntOrStrPushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b varchar(10));") + tk.MustExec("insert into t values(1, 'tiflash');") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "hex(test.t.a)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select hex(a) from t;").CheckAt([]int{0, 2, 4}, rows) + + rows = [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "hex(test.t.b)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select hex(b) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestBinPushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int);") + tk.MustExec("insert into t values(1);") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "bin(test.t.a)->Column#3"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select bin(a) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestEltPushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b varchar(20))") + tk.MustExec("insert into t values(2147483647, '32')") + tk.MustExec("insert into t values(12, 'abc')") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "elt(test.t.a, test.t.b)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select elt(a, b) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestRegexpInstrPushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists test.t;") + tk.MustExec("create table test.t (expr varchar(30), pattern varchar(30), pos int, occur int, ret_op int, match_type varchar(30));") + tk.MustExec("insert into test.t values ('123', '12.', 1, 1, 0, ''), ('aBb', 'bb', 1, 1, 0, 'i'), ('ab\nabc', '^abc$', 1, 1, 0, 'm');") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "regexp_instr(test.t.expr, test.t.pattern, 1, 1, 0, test.t.match_type)->Column#8"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select regexp_instr(expr, pattern, 1, 1, 0, match_type) as res from test.t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestRegexpSubstrPushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists test.t;") + tk.MustExec("create table test.t (expr varchar(30), pattern varchar(30), pos int, occur int, match_type varchar(30));") + tk.MustExec("insert into test.t values ('123', '12.', 1, 1, ''), ('aBb', 'bb', 1, 1, 'i'), ('ab\nabc', '^abc$', 1, 1, 'm');") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "regexp_substr(test.t.expr, test.t.pattern, 1, 1, test.t.match_type)->Column#7"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select regexp_substr(expr, pattern, 1, 1, match_type) as res from test.t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestRegexpReplacePushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists test.t;") + tk.MustExec("create table test.t (expr varchar(30), pattern varchar(30), repl varchar(30), pos int, occur int, match_type varchar(30));") + tk.MustExec("insert into test.t values ('123', '12.', '233', 1, 1, ''), ('aBb', 'bb', 'bc', 1, 1, 'i'), ('ab\nabc', '^abc$', 'd', 1, 1, 'm');") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "regexp_replace(test.t.expr, test.t.pattern, test.t.repl, 1, 1, test.t.match_type)->Column#8"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select regexp_replace(expr, pattern, repl, 1, 1, match_type) as res from test.t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestCastTimeAsDurationToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a date, b datetime(4))") + tk.MustExec("insert into t values('2021-10-26', '2021-10-26')") + tk.MustExec("insert into t values('2021-10-26', '2021-10-26 11:11:11')") + tk.MustExec("insert into t values('2021-10-26', '2021-10-26 11:11:11.111111')") + tk.MustExec("insert into t values('2021-10-26', '2021-10-26 11:11:11.123456')") + tk.MustExec("insert into t values('2021-10-26', '2021-10-26 11:11:11.999999')") + + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "cast(test.t.a, time BINARY)->Column#4, cast(test.t.b, time BINARY)->Column#5"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select cast(a as time), cast(b as time) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestUnhexPushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b varchar(20));") + tk.MustExec("insert into t values(6162, '7469666C617368');") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "unhex(cast(test.t.a, var_string(20)))->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select unhex(a) from t;").CheckAt([]int{0, 2, 4}, rows) + + rows = [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "unhex(test.t.b)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select unhex(b) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestLeastGretestStringPushDownToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a varchar(20), b varchar(20))") + tk.MustExec("insert into t values('123', '234')") + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "least(test.t.a, test.t.b)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select least(a, b) from t;").CheckAt([]int{0, 2, 4}, rows) + + rows = [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "greatest(test.t.a, test.t.b)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select greatest(a, b) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestTiFlashReadForWriteStmt(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int)") + tk.MustExec("insert into t values(1, 2)") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t2(a int)") + tk.MustExec("set @@tidb_allow_mpp=1") + + // Default should be 1 + tk.MustQuery("select @@tidb_enable_tiflash_read_for_write_stmt").Check(testkit.Rows("1")) + // Set ON + tk.MustExec("set @@tidb_enable_tiflash_read_for_write_stmt = ON") + tk.MustQuery("show warnings").Check(testkit.Rows()) + tk.MustQuery("select @@tidb_enable_tiflash_read_for_write_stmt").Check(testkit.Rows("1")) + // Set OFF + tk.MustExec("set @@tidb_enable_tiflash_read_for_write_stmt = OFF") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 tidb_enable_tiflash_read_for_write_stmt is always turned on. This variable has been deprecated and will be removed in the future releases")) + tk.MustQuery("select @@tidb_enable_tiflash_read_for_write_stmt").Check(testkit.Rows("1")) + + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + tbl2, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t2", L: "t2"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl2.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + checkRes := func(r [][]any, pos int, expected string) { + check := false + for i := range r { + if r[i][pos] == expected { + check = true + break + } + } + require.Equal(t, check, true) + } + + check := func(query string) { + // If sql mode is strict, read does not push down to tiflash + tk.MustExec("set @@sql_mode = 'strict_trans_tables'") + tk.MustExec("set @@tidb_enforce_mpp=0") + rs := tk.MustQuery(query).Rows() + checkRes(rs, 2, "cop[tikv]") + tk.MustQuery("show warnings").Check(testkit.Rows()) + + // If sql mode is strict and tidb_enforce_mpp is on, read does not push down to tiflash + // and should return a warning. + tk.MustExec("set @@tidb_enforce_mpp=1") + rs = tk.MustQuery(query).Rows() + checkRes(rs, 2, "cop[tikv]") + rs = tk.MustQuery("show warnings").Rows() + checkRes(rs, 2, "MPP mode may be blocked because the query is not readonly and sql mode is strict.") + + // If sql mode is not strict, read should push down to tiflash + tk.MustExec("set @@sql_mode = ''") + rs = tk.MustQuery(query).Rows() + checkRes(rs, 2, "mpp[tiflash]") + tk.MustQuery("show warnings").Check(testkit.Rows()) + } + + // Insert into ... select + check("explain insert into t2 select a+b from t") + check("explain insert into t2 select t.a from t2 join t on t2.a = t.a") + + // Replace into ... select + check("explain replace into t2 select a+b from t") + + // CTE + check("explain update t set a=a+1 where b in (select a from t2 where t.a > t2.a)") +} + +func TestPointGetWithSelectLock(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int, b int, primary key(a, b));") + tk.MustExec("create table t1(c int unique, d int);") + tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + tbl1, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t1", L: "t1"}) + require.NoError(t, err) + // Set the hacked TiFlash replica for explain tests. + tbl1.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true} + + sqls := []string{ + "explain select a, b from t where (a = 1 and b = 2) or (a =2 and b = 1) for update;", + "explain select a, b from t where a = 1 and b = 2 for update;", + "explain select c, d from t1 where c = 1 for update;", + "explain select c, d from t1 where c = 1 and d = 1 for update;", + "explain select c, d from t1 where (c = 1 or c = 2 )and d = 1 for update;", + "explain select c, d from t1 where c in (1,2,3,4) for update;", + } + tk.MustExec("set @@tidb_enable_tiflash_read_for_write_stmt = on;") + tk.MustExec("set @@sql_mode='';") + tk.MustExec("set @@tidb_isolation_read_engines='tidb,tiflash';") + tk.MustExec("begin;") + // assert point get / batch point get can't work with tiflash in interaction txn + for _, sql := range sqls { + err = tk.ExecToErr(sql) + require.Error(t, err) + } + // assert point get / batch point get can work with tikv in interaction txn + tk.MustExec("set @@tidb_isolation_read_engines='tidb,tikv,tiflash';") + for _, sql := range sqls { + tk.MustQuery(sql) + } + tk.MustExec("commit") + // assert point get / batch point get can work with tiflash in auto commit + tk.MustExec("set @@tidb_isolation_read_engines='tidb,tiflash';") + for _, sql := range sqls { + tk.MustQuery(sql) + } +} + +func TestPlanCacheForIndexRangeFallback(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec(`set @@tidb_enable_prepared_plan_cache=1`) + tk.MustExec("set @@tidb_enable_collect_execution_info=0") // In this way `explain for connection id` doesn't display execution info. + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (a varchar(10), b varchar(10), c varchar(10), index idx_a_b(a, b))") + tk.MustExec("set @@tidb_opt_range_max_size=1330") // 1330 is the memory usage of ["aa","aa"], ["bb","bb"], ["cc","cc"], ["dd","dd"], ["ee","ee"]. + rows := tk.MustQuery("explain format='brief' select * from t where a in ('aa', 'bb', 'cc', 'dd', 'ee')").Rows() + require.True(t, strings.Contains(rows[1][0].(string), "IndexRangeScan")) + require.True(t, strings.Contains(rows[1][4].(string), "range:[\"aa\",\"aa\"], [\"bb\",\"bb\"], [\"cc\",\"cc\"], [\"dd\",\"dd\"], [\"ee\",\"ee\"]")) + rows = tk.MustQuery("explain format='brief' select * from t where a in ('aaaaaaaaaa', 'bbbbbbbbbb', 'cccccccccc', 'dddddddddd', 'eeeeeeeeee')").Rows() + // 1330 is not enough for ["aaaaaaaaaa","aaaaaaaaaa"], ["bbbbbbbbbb","bbbbbbbbbb"], ["cccccccccc","cccccccccc"], ["dddddddddd","dddddddddd"], ["eeeeeeeeee","eeeeeeeeee"]. + // So it falls back to table full scan. + require.True(t, strings.Contains(rows[2][0].(string), "TableFullScan")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1330 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen")) + + // Test rebuilding ranges for the cached plan doesn't have memory limit. + tk.MustExec("prepare stmt1 from 'select * from t where a in (?, ?, ?, ?, ?)'") + tk.MustExec("set @a='aa', @b='bb', @c='cc', @d='dd', @e='ee'") + tk.MustExec("execute stmt1 using @a, @b, @c, @d, @e") + tk.MustQuery("show warnings").Check(testkit.Rows()) // Range fallback doesn't happen and the plan can be put into cache. + tk.MustExec("set @a='aaaaaaaaaa', @b='bbbbbbbbbb', @c='cccccccccc', @d='dddddddddd', @e='eeeeeeeeee'") + tk.MustExec("execute stmt1 using @a, @b, @c, @d, @e") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustExec("execute stmt1 using @a, @b, @c, @d, @e") + tkProcess := tk.Session().ShowProcess() + ps := []*util.ProcessInfo{tkProcess} + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) + rows = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows() + // We don't limit range mem usage when rebuilding ranges for the cached plan. + // So ["aaaaaaaaaa","aaaaaaaaaa"], ["bbbbbbbbbb","bbbbbbbbbb"], ["cccccccccc","cccccccccc"], ["dddddddddd","dddddddddd"], ["eeeeeeeeee","eeeeeeeeee"] can still be built even if its mem usage exceeds 1330. + require.True(t, strings.Contains(rows[1][0].(string), "IndexRangeScan")) + require.True(t, strings.Contains(rows[1][4].(string), "range:[\"aaaaaaaaaa\",\"aaaaaaaaaa\"], [\"bbbbbbbbbb\",\"bbbbbbbbbb\"], [\"cccccccccc\",\"cccccccccc\"], [\"dddddddddd\",\"dddddddddd\"], [\"eeeeeeeeee\",\"eeeeeeeeee\"]")) + + // Test the plan with range fallback would not be put into cache. + tk.MustExec("prepare stmt2 from 'select * from t where a in (?, ?, ?, ?, ?) and b in (?, ?, ?, ?, ?)'") + tk.MustExec("set @a='aa', @b='bb', @c='cc', @d='dd', @e='ee', @f='ff', @g='gg', @h='hh', @i='ii', @j='jj'") + tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e, @f, @g, @h, @i, @j") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 Memory capacity of 1330 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen", + "Warning 1105 skip prepared plan-cache: in-list is too long")) + tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e, @f, @g, @h, @i, @j") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) +} + +func TestCorColRangeWithRangeMaxSize(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") + tk.MustExec("create table t1(a int)") + tk.MustExec("create table t2 (a int, b int, c int, index idx_a_b(a, b))") + tk.MustExec("create table t3(a int primary key)") + tk.MustExec("insert into t1 values (2), (4), (6)") + tk.MustExec("insert into t2 (a, b) values (1, 2), (3, 2), (5, 2)") + tk.MustExec("insert into t3 values (2), (4)") + tk.MustExec("insert into mysql.opt_rule_blacklist value(\"decorrelate\")") + tk.MustExec("admin reload opt_rule_blacklist") + defer func() { + tk.MustExec("delete from mysql.opt_rule_blacklist where name = \"decorrelate\"") + tk.MustExec("admin reload opt_rule_blacklist") + }() + + // Correlated column in index range. + tk.MustExec("set @@tidb_opt_range_max_size=1000") + rows := tk.MustQuery("explain format='brief' select * from t1 where exists (select * from t2 where t2.a in (1, 3, 5) and b >= 2 and t2.b = t1.a)").Rows() + // 1000 is not enough for [1 2,1 +inf], [3 2,3 +inf], [5 2,5 +inf]. So b >= 2 is not used to build ranges. + require.True(t, strings.Contains(rows[4][0].(string), "Selection")) + require.True(t, strings.Contains(rows[4][4].(string), "ge(test.t2.b, 2)")) + // 1000 is not enough for [1 ?,1 ?], [3 ?,3 ?], [5 ?,5 ?] but we don't restrict range mem usage when appending col = cor_col + // conditions to access conditions in SplitCorColAccessCondFromFilters. + require.True(t, strings.Contains(rows[5][0].(string), "IndexRangeScan")) + require.True(t, strings.Contains(rows[5][4].(string), "range: decided by [in(test.t2.a, 1, 3, 5) eq(test.t2.b, test.t1.a)]")) + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1000 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen")) + // We need to rebuild index ranges each time the value of correlated column test.t1.a changes. We don't restrict range + // mem usage when rebuilding index ranges, otherwise range fallback would happen when rebuilding index ranges, causing + // to wrong query results. + tk.MustQuery("select * from t1 where exists (select * from t2 where t2.a in (1, 3, 5) and b >= 2 and t2.b = t1.a)").Check(testkit.Rows("2")) + + // Correlated column in table range. + tk.MustExec("set @@tidb_opt_range_max_size=1") + rows = tk.MustQuery("explain format='brief' select * from t1 where exists (select * from t3 where t3.a = t1.a)").Rows() + // 1 is not enough for [?,?] but we don't restrict range mem usage when adding col = cor_col to access conditions. + require.True(t, strings.Contains(rows[4][0].(string), "TableRangeScan")) + require.True(t, strings.Contains(rows[4][4].(string), "range: decided by [eq(test.t3.a, test.t1.a)]")) + tk.MustQuery("show warnings").Check(testkit.Rows()) + // We need to rebuild table ranges each time the value of correlated column test.t1.a changes. We don't restrict range + // mem usage when rebuilding table ranges, otherwise range fallback would happen when rebuilding table ranges, causing + // to wrong query results. + tk.MustQuery("select * from t1 where exists (select * from t3 where t3.a = t1.a)").Check(testkit.Rows("2", "4")) +} + +// TestExplainAnalyzeDMLCommit covers the issue #37373. +func TestExplainAnalyzeDMLCommit(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c1 int key, c2 int);") + tk.MustExec("insert into t values (1, 1)") + + err := failpoint.Enable("github.com/pingcap/tidb/pkg/session/mockSleepBeforeTxnCommit", "return(500)") + require.NoError(t, err) + defer func() { + _ = failpoint.Disable("github.com/pingcap/tidb/pkg/session/mockSleepBeforeTxnCommit") + }() + // The commit is paused by the failpoint, after the fix the explain statement + // execution should proceed after the commit finishes. + _, err = tk.Exec("explain analyze delete from t;") + require.NoError(t, err) + tk.MustQuery("select * from t").Check(testkit.Rows()) +} + +func TestPlanCacheForIndexJoinRangeFallback(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`set @@tidb_enable_prepared_plan_cache=1`) + tk.MustExec("set @@tidb_enable_collect_execution_info=0") + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1(a int, b varchar(10), c varchar(10), index idx_a_b(a, b))") + tk.MustExec("create table t2(d int)") + tk.MustExec("set @@tidb_opt_range_max_size=1260") + // 1260 is enough for [? a,? a], [? b,? b], [? c,? c] but is not enough for [? aaaaaa,? aaaaaa], [? bbbbbb,? bbbbbb], [? cccccc,? cccccc]. + rows := tk.MustQuery("explain format='brief' select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in ('a', 'b', 'c')").Rows() + require.True(t, strings.Contains(rows[6][4].(string), "range: decided by [eq(test.t1.a, test.t2.d) in(test.t1.b, a, b, c)]")) + tk.MustQuery("show warnings").Check(testkit.Rows()) + rows = tk.MustQuery("explain format='brief' select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in ('aaaaaa', 'bbbbbb', 'cccccc');").Rows() + require.Contains(t, rows[6][4].(string), "range: decided by [eq(test.t1.a, test.t2.d)]") + tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1260 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen")) + + tk.MustExec("prepare stmt1 from 'select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in (?, ?, ?)'") + tk.MustExec("set @a='a', @b='b', @c='c'") + tk.MustExec("execute stmt1 using @a, @b, @c") + tk.MustQuery("show warnings").Check(testkit.Rows()) + tk.MustExec("set @a='aaaaaa', @b='bbbbbb', @c='cccccc'") + tk.MustExec("execute stmt1 using @a, @b, @c") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + tk.MustExec("execute stmt1 using @a, @b, @c") + tkProcess := tk.Session().ShowProcess() + ps := []*util.ProcessInfo{tkProcess} + tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps}) + rows = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows() + // We don't limit range mem usage when rebuilding index join ranges for the cached plan. So [? aaaaaa,? aaaaaa], [? bbbbbb,? bbbbbb], [? cccccc,? cccccc] can be built. + require.Contains(t, rows[6][4].(string), "range: decided by [eq(test.t1.a, test.t2.d) in(test.t1.b, aaaaaa, bbbbbb, cccccc)]") + + // Test the plan with range fallback would not be put into cache. + tk.MustExec("prepare stmt2 from 'select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in (?, ?, ?, ?, ?)'") + tk.MustExec("set @a='a', @b='b', @c='c', @d='d', @e='e'") + tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e") + tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 Memory capacity of 1260 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen", + "Warning 1105 skip prepared plan-cache: in-list is too long")) + tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) +} + +func TestIsIPv4ToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(v4 varchar(100), v6 varchar(100))") + tk.MustExec("insert into t values('123.123.123.123', 'F746:C349:48E3:22F2:81E0:0EA8:E7B6:8286')") + tk.MustExec("insert into t values('0.0.0.0', '0000:0000:0000:0000:0000:0000:0000:0000')") + tk.MustExec("insert into t values('127.0.0.1', '2001:0:2851:b9f0:6d:2326:9036:f37a')") + + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "is_ipv4(test.t.v4)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select is_ipv4(v4) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestIsIPv6ToTiFlash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(v4 varchar(100), v6 varchar(100))") + tk.MustExec("insert into t values('123.123.123.123', 'F746:C349:48E3:22F2:81E0:0EA8:E7B6:8286')") + tk.MustExec("insert into t values('0.0.0.0', '0000:0000:0000:0000:0000:0000:0000:0000')") + tk.MustExec("insert into t values('127.0.0.1', '2001:0:2851:b9f0:6d:2326:9036:f37a')") + + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + rows := [][]any{ + {"TableReader_10", "root", "MppVersion: 2, data:ExchangeSender_9"}, + {"└─ExchangeSender_9", "mpp[tiflash]", "ExchangeType: PassThrough"}, + {" └─Projection_4", "mpp[tiflash]", "is_ipv6(test.t.v6)->Column#4"}, + {" └─TableFullScan_8", "mpp[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select is_ipv6(v6) from t;").CheckAt([]int{0, 2, 4}, rows) +} + +// https://github.com/pingcap/tidb/issues/41355 +// The "virtual generated column" push down is not supported now. +// This test covers: TopN, Projection, Selection. +func TestVirtualExprPushDown(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t;") + tk.MustExec("CREATE TABLE t (c1 int DEFAULT 0, c2 int GENERATED ALWAYS AS (abs(c1)) VIRTUAL);") + tk.MustExec("insert into t(c1) values(1), (-1), (2), (-2), (99), (-99);") + tk.MustExec("set @@tidb_isolation_read_engines = 'tikv'") + tk.MustExec("set @@session.tidb_allow_tiflash_cop=ON") + + // TopN to tikv. + rows := [][]any{ + {"TopN_7", "root", "test.t.c2, offset:0, count:2"}, + {"└─TableReader_13", "root", "data:TableFullScan_12"}, + {" └─TableFullScan_12", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select * from t order by c2 limit 2;").CheckAt([]int{0, 2, 4}, rows) + + // Projection to tikv. + rows = [][]any{ + {"Projection_3", "root", "plus(test.t.c1, test.t.c2)->Column#4"}, + {"└─TableReader_5", "root", "data:TableFullScan_4"}, + {" └─TableFullScan_4", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustExec("set session tidb_opt_projection_push_down='ON';") + tk.MustQuery("explain select c1 + c2 from t;").CheckAt([]int{0, 2, 4}, rows) + tk.MustExec("set session tidb_opt_projection_push_down='OFF';") + + // Selection to tikv. + rows = [][]any{ + {"Selection_7", "root", "gt(test.t.c2, 1)"}, + {"└─TableReader_6", "root", "data:TableFullScan_5"}, + {" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select * from t where c2 > 1;").CheckAt([]int{0, 2, 4}, rows) + + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + // TopN to tiflash. + rows = [][]any{ + {"TopN_7", "root", "test.t.c2, offset:0, count:2"}, + {"└─TableReader_15", "root", "data:TableFullScan_14"}, + {" └─TableFullScan_14", "cop[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select * from t order by c2 limit 2;").CheckAt([]int{0, 2, 4}, rows) + + // Projection to tiflash. + rows = [][]any{ + {"Projection_3", "root", "plus(test.t.c1, test.t.c2)->Column#4"}, + {"└─TableReader_6", "root", "data:TableFullScan_5"}, + {" └─TableFullScan_5", "cop[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustExec("set session tidb_opt_projection_push_down='ON';") + tk.MustQuery("explain select c1 + c2 from t;").CheckAt([]int{0, 2, 4}, rows) + tk.MustExec("set session tidb_opt_projection_push_down='OFF';") + + // Selection to tiflash. + rows = [][]any{ + {"Selection_8", "root", "gt(test.t.c2, 1)"}, + {"└─TableReader_7", "root", "data:TableFullScan_6"}, + {" └─TableFullScan_6", "cop[tiflash]", "keep order:false, stats:pseudo"}, + } + tk.MustQuery("explain select * from t where c2 > 1;").CheckAt([]int{0, 2, 4}, rows) +} + +func TestWindowRangeFramePushDownTiflash(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop table if exists test.first_range;") + tk.MustExec("create table test.first_range(p int not null, o int not null, v int not null, o_datetime datetime not null, o_time time not null);") + tk.MustExec("insert into test.first_range (p, o, v, o_datetime, o_time) values (0, 0, 0, '2023-9-20 11:17:10', '11:17:10');") + + tk.MustExec("drop table if exists test.first_range_d64;") + tk.MustExec("create table test.first_range_d64(p int not null, o decimal(17,1) not null, v int not null);") + tk.MustExec("insert into test.first_range_d64 (p, o, v) values (0, 0.1, 0), (1, 1.0, 1), (1, 2.1, 2), (1, 4.1, 4), (1, 8.1, 8), (2, 0.0, 0), (2, 3.1, 3), (2, 10.0, 10), (2, 13.1, 13), (2, 15.1, 15), (3, 1.1, 1), (3, 2.9, 3), (3, 5.1, 5), (3, 9.1, 9), (3, 15.0, 15), (3, 20.1, 20), (3, 31.1, 31);") + + tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1") + tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'") + + // Create virtual tiflash replica info. + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tbl := range is.SchemaTables(db.Name) { + tblInfo := tbl.Meta() + if tblInfo.Name.L == "first_range" || tblInfo.Name.L == "first_range_d64" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + tk.MustExec(`set @@tidb_max_tiflash_threads=20`) + + tk.MustQuery("explain select *, first_value(v) over (partition by p order by o range between 3 preceding and 0 following) as a from test.first_range;").Check(testkit.Rows( + "TableReader_23 10000.00 root MppVersion: 2, data:ExchangeSender_22", + "└─ExchangeSender_22 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Window_21 10000.00 mpp[tiflash] first_value(test.first_range.v)->Column#8 over(partition by test.first_range.p order by test.first_range.o range between 3 preceding and 0 following), stream_count: 20", + " └─Sort_13 10000.00 mpp[tiflash] test.first_range.p, test.first_range.o, stream_count: 20", + " └─ExchangeReceiver_12 10000.00 mpp[tiflash] stream_count: 20", + " └─ExchangeSender_11 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.first_range.p, collate: binary], stream_count: 20", + " └─TableFullScan_10 10000.00 mpp[tiflash] table:first_range keep order:false, stats:pseudo")) + + tk.MustQuery("explain select *, first_value(v) over (partition by p order by o range between 3 preceding and 2.9E0 following) as a from test.first_range;").Check(testkit.Rows( + "TableReader_23 10000.00 root MppVersion: 2, data:ExchangeSender_22", + "└─ExchangeSender_22 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Window_21 10000.00 mpp[tiflash] first_value(test.first_range.v)->Column#8 over(partition by test.first_range.p order by test.first_range.o range between 3 preceding and 2.9 following), stream_count: 20", + " └─Sort_13 10000.00 mpp[tiflash] test.first_range.p, test.first_range.o, stream_count: 20", + " └─ExchangeReceiver_12 10000.00 mpp[tiflash] stream_count: 20", + " └─ExchangeSender_11 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.first_range.p, collate: binary], stream_count: 20", + " └─TableFullScan_10 10000.00 mpp[tiflash] table:first_range keep order:false, stats:pseudo")) + + tk.MustQuery("explain select *, first_value(v) over (partition by p order by o range between 2.3 preceding and 0 following) as a from test.first_range_d64;").Check(testkit.Rows( + "TableReader_23 10000.00 root MppVersion: 2, data:ExchangeSender_22", + "└─ExchangeSender_22 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Window_21 10000.00 mpp[tiflash] first_value(test.first_range_d64.v)->Column#6 over(partition by test.first_range_d64.p order by test.first_range_d64.o range between 2.3 preceding and 0 following), stream_count: 20", + " └─Sort_13 10000.00 mpp[tiflash] test.first_range_d64.p, test.first_range_d64.o, stream_count: 20", + " └─ExchangeReceiver_12 10000.00 mpp[tiflash] stream_count: 20", + " └─ExchangeSender_11 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.first_range_d64.p, collate: binary], stream_count: 20", + " └─TableFullScan_10 10000.00 mpp[tiflash] table:first_range_d64 keep order:false, stats:pseudo")) + + tk.MustQuery("explain select *, first_value(v) over (partition by p order by o_datetime range between interval 1 day preceding and interval 1 day following) as a from test.first_range;").Check(testkit.Rows( + "TableReader_23 10000.00 root MppVersion: 2, data:ExchangeSender_22", + "└─ExchangeSender_22 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─Window_21 10000.00 mpp[tiflash] first_value(test.first_range.v)->Column#8 over(partition by test.first_range.p order by test.first_range.o_datetime range between interval 1 \"DAY\" preceding and interval 1 \"DAY\" following), stream_count: 20", + " └─Sort_13 10000.00 mpp[tiflash] test.first_range.p, test.first_range.o_datetime, stream_count: 20", + " └─ExchangeReceiver_12 10000.00 mpp[tiflash] stream_count: 20", + " └─ExchangeSender_11 10000.00 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.first_range.p, collate: binary], stream_count: 20", + " └─TableFullScan_10 10000.00 mpp[tiflash] table:first_range keep order:false, stats:pseudo")) + + tk.MustQuery("explain select *, first_value(v) over (partition by p order by o_time range between interval 1 day preceding and interval 1 day following) as a from test.first_range;").Check(testkit.Rows( + "Shuffle_13 10000.00 root execution info: concurrency:5, data sources:[TableReader_11]", + "└─Window_8 10000.00 root first_value(test.first_range.v)->Column#8 over(partition by test.first_range.p order by test.first_range.o_time range between interval 1 \"DAY\" preceding and interval 1 \"DAY\" following)", + " └─Sort_12 10000.00 root test.first_range.p, test.first_range.o_time", + " └─ShuffleReceiver_14 10000.00 root ", + " └─TableReader_11 10000.00 root MppVersion: 2, data:ExchangeSender_10", + " └─ExchangeSender_10 10000.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TableFullScan_9 10000.00 mpp[tiflash] table:first_range keep order:false, stats:pseudo")) +} + +func TestIssue46556(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`CREATE TABLE t0(c0 BLOB);`) + tk.MustExec(`CREATE definer='root'@'localhost' VIEW v0(c0) AS SELECT NULL FROM t0 GROUP BY NULL;`) + tk.MustExec(`SELECT t0.c0 FROM t0 NATURAL JOIN v0 WHERE v0.c0 LIKE v0.c0;`) // no error + tk.MustQuery(`explain format='brief' SELECT t0.c0 FROM t0 NATURAL JOIN v0 WHERE v0.c0 LIKE v0.c0`).Check( + testkit.Rows(`HashJoin 0.00 root inner join, equal:[eq(Column#9, Column#10)]`, + `├─Projection(Build) 0.00 root ->Column#9`, + `│ └─TableDual 0.00 root rows:0`, + `└─Projection(Probe) 9990.00 root test.t0.c0, cast(test.t0.c0, double BINARY)->Column#10`, + ` └─TableReader 9990.00 root data:Selection`, + ` └─Selection 9990.00 cop[tikv] not(isnull(test.t0.c0))`, + ` └─TableFullScan 10000.00 cop[tikv] table:t0 keep order:false, stats:pseudo`)) +} + +// https://github.com/pingcap/tidb/issues/41458 +func TestIssue41458(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil, nil)) + tk.MustExec("use test") + tk.MustExec(`create table t (a int, b int, c int, index ia(a));`) + tk.MustExec("select * from t t1 join t t2 on t1.b = t2.b join t t3 on t2.b=t3.b join t t4 on t3.b=t4.b where t3.a=1 and t2.a=2;") + rawRows := tk.MustQuery("select plan from information_schema.statements_summary where SCHEMA_NAME = 'test' and STMT_TYPE = 'Select';").Sort().Rows() + plan := rawRows[0][0].(string) + rows := strings.Split(plan, "\n") + rows = rows[1:] + expectedRes := []string{ + "Projection", + "└─HashJoin", + " ├─HashJoin", + " │ ├─HashJoin", + " │ │ ├─IndexLookUp", + " │ │ │ ├─IndexRangeScan", + " │ │ │ └─Selection", + " │ │ │ └─TableRowIDScan", + " │ │ └─IndexLookUp", + " │ │ ├─IndexRangeScan", + " │ │ └─Selection", + " │ │ └─TableRowIDScan", + " │ └─TableReader", + " │ └─Selection", + " │ └─TableFullScan", + " └─TableReader", + " └─Selection", + " └─TableFullScan", + } + for i, row := range rows { + fields := strings.Split(row, "\t") + fields = strings.Split(fields[1], "_") + op := fields[0] + require.Equalf(t, expectedRes[i], op, fmt.Sprintf("Mismatch at index %d.", i)) + } +} + +func TestIssue48257(t *testing.T) { + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + h := dom.StatsHandle() + oriLease := h.Lease() + h.SetLease(1) + defer func() { + h.SetLease(oriLease) + }() + tk.MustExec("use test") + + // 1. test sync load + tk.MustExec("create table t(a int)") + tk.MustExec("insert into t value(1)") + require.NoError(t, h.DumpStatsDeltaToKV(true)) + require.NoError(t, h.Update(dom.InfoSchema())) + tk.MustExec("analyze table t") + tk.MustQuery("explain format = brief select * from t").Check(testkit.Rows( + "TableReader 1.00 root data:TableFullScan", + "└─TableFullScan 1.00 cop[tikv] table:t keep order:false", + )) + tk.MustExec("insert into t value(1)") + require.NoError(t, h.DumpStatsDeltaToKV(true)) + require.NoError(t, h.Update(dom.InfoSchema())) + tk.MustQuery("explain format = brief select * from t").Check(testkit.Rows( + "TableReader 2.00 root data:TableFullScan", + "└─TableFullScan 2.00 cop[tikv] table:t keep order:false", + )) + tk.MustExec("set tidb_opt_objective='determinate'") + tk.MustQuery("explain format = brief select * from t").Check(testkit.Rows( + "TableReader 1.00 root data:TableFullScan", + "└─TableFullScan 1.00 cop[tikv] table:t keep order:false", + )) + tk.MustExec("set tidb_opt_objective='moderate'") + + // 2. test async load + tk.MustExec("set tidb_stats_load_sync_wait = 0") + tk.MustExec("create table t1(a int)") + tk.MustExec("insert into t1 value(1)") + require.NoError(t, h.DumpStatsDeltaToKV(true)) + require.NoError(t, h.Update(dom.InfoSchema())) + tk.MustExec("analyze table t1") + tk.MustQuery("explain format = brief select * from t1").Check(testkit.Rows( + "TableReader 1.00 root data:TableFullScan", + "└─TableFullScan 1.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + )) + tk.MustExec("insert into t1 value(1)") + require.NoError(t, h.DumpStatsDeltaToKV(true)) + require.NoError(t, h.Update(dom.InfoSchema())) + tk.MustQuery("explain format = brief select * from t1").Check(testkit.Rows( + "TableReader 2.00 root data:TableFullScan", + "└─TableFullScan 2.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + )) + tk.MustExec("set tidb_opt_objective='determinate'") + tk.MustQuery("explain format = brief select * from t1").Check(testkit.Rows( + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + )) + require.NoError(t, h.LoadNeededHistograms()) + tk.MustQuery("explain format = brief select * from t1").Check(testkit.Rows( + "TableReader 1.00 root data:TableFullScan", + "└─TableFullScan 1.00 cop[tikv] table:t1 keep order:false", + )) +} + +func TestIssue52472(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("CREATE TABLE t1 ( c1 int);") + tk.MustExec("CREATE TABLE t2 ( c1 int unsigned);") + tk.MustExec("CREATE TABLE t3 ( c1 bigint unsigned);") + tk.MustExec("INSERT INTO t1 (c1) VALUES (8);") + tk.MustExec("INSERT INTO t2 (c1) VALUES (2454396638);") + + // union int and unsigned int will be promoted to long long + rs, err := tk.Exec("SELECT c1 FROM t1 UNION ALL SELECT c1 FROM t2") + require.NoError(t, err) + require.Len(t, rs.Fields(), 1) + require.Equal(t, mysql.TypeLonglong, rs.Fields()[0].Column.FieldType.GetType()) + require.NoError(t, rs.Close()) + + // union int (even literal) and unsigned bigint will be promoted to decimal + rs, err = tk.Exec("SELECT 0 UNION ALL SELECT c1 FROM t3") + require.NoError(t, err) + require.Len(t, rs.Fields(), 1) + require.Equal(t, mysql.TypeNewDecimal, rs.Fields()[0].Column.FieldType.GetType()) + require.NoError(t, rs.Close()) +} diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 7f426b77941d4..fc7cafe2e7355 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -1692,7 +1692,7 @@ func unionJoinFieldType(a, b *types.FieldType) *types.FieldType { } else if b.GetType() == mysql.TypeNull { return a } - resultTp := types.NewFieldType(types.MergeFieldType(a.GetType(), b.GetType())) + resultTp := types.AggFieldType([]*types.FieldType{a, b}) // This logic will be intelligible when it is associated with the buildProjection4Union logic. if resultTp.GetType() == mysql.TypeNewDecimal { // The decimal result type will be unsigned only when all the decimals to be united are unsigned. diff --git a/types/field_type.go b/types/field_type.go index 904206df1f282..48a624e18d082 100644 --- a/types/field_type.go +++ b/types/field_type.go @@ -68,7 +68,7 @@ func AggFieldType(tps []*FieldType) *FieldType { currType = *t continue } - mtp := MergeFieldType(currType.GetType(), t.GetType()) + mtp := mergeFieldType(currType.GetType(), t.GetType()) isMixedSign = isMixedSign || (mysql.HasUnsignedFlag(currType.GetFlag()) != mysql.HasUnsignedFlag(t.GetFlag())) currType.SetType(mtp) currType.SetFlag(mergeTypeFlag(currType.GetFlag(), t.GetFlag())) @@ -353,12 +353,16 @@ func DefaultCharsetForType(tp byte) (defaultCharset string, defaultCollation str return charset.CharsetBin, charset.CollationBin } -// MergeFieldType merges two MySQL type to a new type. +// mergeFieldType merges two MySQL type to a new type. // This is used in hybrid field type expression. // For example "select case c when 1 then 2 when 2 then 'tidb' from t;" // The result field type of the case expression is the merged type of the two when clause. // See https://github.com/mysql/mysql-server/blob/8.0/sql/field.cc#L1042 -func MergeFieldType(a byte, b byte) byte { +// +// This function doesn't handle the range bump: for example, when the unsigned long is merged with signed long, +// the result should be longlong. However, this function returns long for this case. Please use `AggFieldType` +// function if you need to handle the range bump. +func mergeFieldType(a byte, b byte) byte { ia := getFieldTypeIndex(a) ib := getFieldTypeIndex(b) return fieldTypeMergeRules[ia][ib]