diff --git a/cmd/explaintest/r/explain_complex.result b/cmd/explaintest/r/explain_complex.result index 13e967b30193d..cb6e6045570a0 100644 --- a/cmd/explaintest/r/explain_complex.result +++ b/cmd/explaintest/r/explain_complex.result @@ -120,9 +120,9 @@ Projection_13 1.00 root test.gad.id, test.dd.id, test.gad.aid, test.gad.cm, test └─HashAgg_19 1.00 root group by:test.dd.dic, test.gad.aid, funcs:firstrow(test.gad.id), firstrow(test.gad.aid), firstrow(test.gad.cm), firstrow(test.gad.p1), firstrow(test.gad.p2), firstrow(test.gad.p3), firstrow(test.gad.p4), firstrow(test.gad.p5), firstrow(test.gad.p6_md5), firstrow(test.gad.p7_md5), firstrow(test.gad.ext), firstrow(test.gad.t), firstrow(test.dd.id), firstrow(test.dd.dic), firstrow(test.dd.ip), firstrow(test.dd.t) └─IndexMergeJoin_30 0.00 root inner join, inner:IndexLookUp_28, outer key:test.gad.aid, inner key:test.dd.aid, other cond:eq(test.dd.ip, test.gad.ip), gt(test.dd.t, test.gad.t) ├─IndexLookUp_28 0.00 root - │ ├─IndexScan_25 10.00 cop table:dd, index:aid, dic, range: decided by [eq(test.dd.aid, test.gad.aid)], keep order:true, stats:pseudo + │ ├─IndexScan_25 0.00 cop table:dd, index:aid, dic, range: decided by [eq(test.dd.aid, test.gad.aid)], keep order:true, stats:pseudo │ └─Selection_27 0.00 cop eq(test.dd.bm, 0), eq(test.dd.pt, "android"), gt(test.dd.t, 1478143908), not(isnull(test.dd.ip)), not(isnull(test.dd.t)) - │ └─TableScan_26 10.00 cop table:dd, keep order:false, stats:pseudo + │ └─TableScan_26 0.00 cop table:dd, keep order:false, stats:pseudo └─IndexLookUp_39 3.33 root ├─IndexScan_36 3333.33 cop table:gad, index:t, range:(1478143908,+inf], keep order:false, stats:pseudo └─Selection_38 3.33 cop eq(test.gad.pt, "android"), not(isnull(test.gad.ip)) @@ -137,9 +137,9 @@ Projection_10 0.00 root test.gad.id, test.sdk.id, test.gad.aid, test.gad.cm, tes │ └─Selection_32 0.00 cop eq(test.gad.bm, 0), eq(test.gad.dit, "mac"), eq(test.gad.pt, "ios"), not(isnull(test.gad.dic)) │ └─TableScan_31 3333.33 cop table:gad, keep order:false, stats:pseudo └─IndexLookUp_22 0.00 root - ├─IndexScan_19 10.00 cop table:sdk, index:aid, dic, range: decided by [eq(test.sdk.aid, test.gad.aid)], keep order:true, stats:pseudo + ├─IndexScan_19 0.00 cop table:sdk, index:aid, dic, range: decided by [eq(test.sdk.aid, test.gad.aid)], keep order:true, stats:pseudo └─Selection_21 0.00 cop eq(test.sdk.bm, 0), eq(test.sdk.pt, "ios"), gt(test.sdk.t, 1477971479), not(isnull(test.sdk.mac)), not(isnull(test.sdk.t)) - └─TableScan_20 10.00 cop table:sdk, keep order:false, stats:pseudo + └─TableScan_20 0.00 cop table:sdk, keep order:false, stats:pseudo explain SELECT cm, p1, p2, p3, p4, p5, p6_md5, p7_md5, count(1) as click_pv, count(DISTINCT ip) as click_ip FROM st WHERE (t between 1478188800 and 1478275200) and aid='cn.sbkcq' and pt='android' GROUP BY cm, p1, p2, p3, p4, p5, p6_md5, p7_md5; id count task operator info Projection_5 1.00 root test.st.cm, test.st.p1, test.st.p2, test.st.p3, test.st.p4, test.st.p5, test.st.p6_md5, test.st.p7_md5, 3_col_0, 3_col_1 @@ -157,9 +157,9 @@ Projection_10 0.00 root test.dt.id, test.dt.aid, test.dt.pt, test.dt.dic, test.d │ └─Selection_52 0.00 cop eq(test.dt.bm, 0), eq(test.dt.pt, "ios"), gt(test.dt.t, 1478185592), not(isnull(test.dt.dic)) │ └─TableScan_51 10000.00 cop table:dt, range:[0,+inf], keep order:false, stats:pseudo └─IndexLookUp_23 0.00 root - ├─IndexScan_20 10.00 cop table:rr, index:aid, dic, range: decided by [eq(test.rr.aid, test.dt.aid) eq(test.rr.dic, test.dt.dic)], keep order:true, stats:pseudo + ├─IndexScan_20 1.25 cop table:rr, index:aid, dic, range: decided by [eq(test.rr.aid, test.dt.aid) eq(test.rr.dic, test.dt.dic)], keep order:true, stats:pseudo └─Selection_22 0.00 cop eq(test.rr.pt, "ios"), gt(test.rr.t, 1478185592) - └─TableScan_21 10.00 cop table:rr, keep order:false, stats:pseudo + └─TableScan_21 1.25 cop table:rr, keep order:false, stats:pseudo explain select pc,cr,count(DISTINCT uid) as pay_users,count(oid) as pay_times,sum(am) as am from pp where ps=2 and ppt>=1478188800 and ppt<1478275200 and pi in ('510017','520017') and uid in ('18089709','18090780') group by pc,cr; id count task operator info Projection_5 1.00 root test.pp.pc, test.pp.cr, 3_col_0, 3_col_1, 3_col_2 @@ -251,11 +251,11 @@ Sort_10 1.00 root test.d.left_value:asc │ │ ├─IndexScan_55 10.00 cop table:d, index:ctx, range:[1,1], keep order:false, stats:pseudo │ │ └─Selection_57 0.01 cop eq(test.d.status, 1000) │ │ └─TableScan_56 10.00 cop table:d, keep order:false, stats:pseudo - │ └─IndexLookUp_37 0.01 root - │ ├─Selection_35 9.99 cop not(isnull(test.p.department_id)) - │ │ └─IndexScan_33 10.00 cop table:p, index:department_id, range: decided by [eq(test.p.department_id, test.d.id)], keep order:true, stats:pseudo - │ └─Selection_36 0.01 cop eq(test.p.status, 1000) - │ └─TableScan_34 9.99 cop table:p, keep order:false, stats:pseudo + │ └─IndexLookUp_37 0.00 root + │ ├─Selection_35 1.25 cop not(isnull(test.p.department_id)) + │ │ └─IndexScan_33 1.25 cop table:p, index:department_id, range: decided by [eq(test.p.department_id, test.d.id)], keep order:true, stats:pseudo + │ └─Selection_36 0.00 cop eq(test.p.status, 1000) + │ └─TableScan_34 1.25 cop table:p, keep order:false, stats:pseudo └─TableReader_68 9.99 root data:Selection_67 └─Selection_67 9.99 cop eq(test.ep.status, 1000), not(isnull(test.ep.position_id)) └─TableScan_66 10000.00 cop table:ep, range:[-inf,+inf], keep order:false, stats:pseudo diff --git a/cmd/explaintest/r/index_join.result b/cmd/explaintest/r/index_join.result index 8ccd7cd0623e5..acbacc0ba6867 100644 --- a/cmd/explaintest/r/index_join.result +++ b/cmd/explaintest/r/index_join.result @@ -35,8 +35,8 @@ id count task operator info IndexMergeJoin_14 8000.00 root semi join, inner:IndexReader_12, outer key:test.t1.a, inner key:test.t2.a ├─TableReader_16 10000.00 root data:TableScan_15 │ └─TableScan_15 10000.00 cop table:t1, range:[-inf,+inf], keep order:false, stats:pseudo -└─IndexReader_12 10.00 root index:IndexScan_11 - └─IndexScan_11 10.00 cop table:t2, index:a, range: decided by [eq(test.t2.a, test.t1.a)], keep order:true, stats:pseudo +└─IndexReader_12 1.25 root index:IndexScan_11 + └─IndexScan_11 1.25 cop table:t2, index:a, range: decided by [eq(test.t2.a, test.t1.a)], keep order:true, stats:pseudo show warnings; Level Code Message set @@tidb_opt_insubq_to_join_and_agg=1; @@ -46,10 +46,10 @@ create table t2(a int not null, b int not null, key a(a)); explain select /*+ TIDB_INLJ(t1) */ * from t1 where t1.a in (select t2.a from t2); id count task operator info Projection_8 10000.00 root test.t1.a, test.t1.b -└─IndexJoin_12 10000.00 root inner join, inner:IndexLookUp_11, outer key:test.t2.a, inner key:test.t1.a - ├─IndexLookUp_11 10.00 root - │ ├─IndexScan_9 10.00 cop table:t1, index:a, range: decided by [eq(test.t1.a, test.t2.a)], keep order:false, stats:pseudo - │ └─TableScan_10 10.00 cop table:t1, keep order:false, stats:pseudo +└─IndexMergeJoin_17 10000.00 root inner join, inner:IndexLookUp_15, outer key:test.t2.a, inner key:test.t1.a + ├─IndexLookUp_15 1.25 root + │ ├─IndexScan_13 1.25 cop table:t1, index:a, range: decided by [eq(test.t1.a, test.t2.a)], keep order:true, stats:pseudo + │ └─TableScan_14 1.25 cop table:t1, keep order:false, stats:pseudo └─StreamAgg_22 8000.00 root group by:test.t2.a, funcs:firstrow(test.t2.a) └─IndexReader_35 10000.00 root index:IndexScan_34 └─IndexScan_34 10000.00 cop table:t2, index:a, range:[NULL,+inf], keep order:true, stats:pseudo diff --git a/cmd/explaintest/r/topn_push_down.result b/cmd/explaintest/r/topn_push_down.result index a4cedc3e587c3..74480db2fde97 100644 --- a/cmd/explaintest/r/topn_push_down.result +++ b/cmd/explaintest/r/topn_push_down.result @@ -177,13 +177,13 @@ Projection_13 0.00 root test.te.expect_time │ │ │ └─IndexScan_86 10.00 cop table:tr, index:shop_identy, trade_status, business_type, trade_pay_status, trade_type, delivery_type, source, biz_date, range:[810094178,810094178], keep order:false, stats:pseudo │ │ └─Selection_89 0.00 cop eq(test.tr.brand_identy, 32314), eq(test.tr.domain_type, 2) │ │ └─TableScan_87 0.00 cop table:tr, keep order:false, stats:pseudo - │ └─IndexLookUp_45 0.25 root - │ ├─IndexScan_42 10.00 cop table:te, index:trade_id, range: decided by [eq(test.te.trade_id, test.tr.id)], keep order:true, stats:pseudo - │ └─Selection_44 0.25 cop ge(test.te.expect_time, 2018-04-23 00:00:00.000000), le(test.te.expect_time, 2018-04-23 23:59:59.000000) - │ └─TableScan_43 10.00 cop table:te, keep order:false, stats:pseudo - └─IndexReader_115 9.99 root index:Selection_114 - └─Selection_114 9.99 cop not(isnull(test.p.relate_id)) - └─IndexScan_113 10.00 cop table:p, index:relate_id, range: decided by [eq(test.p.relate_id, test.tr.id)], keep order:false, stats:pseudo + │ └─IndexLookUp_45 0.03 root + │ ├─IndexScan_42 1.25 cop table:te, index:trade_id, range: decided by [eq(test.te.trade_id, test.tr.id)], keep order:true, stats:pseudo + │ └─Selection_44 0.03 cop ge(test.te.expect_time, 2018-04-23 00:00:00.000000), le(test.te.expect_time, 2018-04-23 23:59:59.000000) + │ └─TableScan_43 1.25 cop table:te, keep order:false, stats:pseudo + └─IndexReader_115 1.25 root index:Selection_114 + └─Selection_114 1.25 cop not(isnull(test.p.relate_id)) + └─IndexScan_113 1.25 cop table:p, index:relate_id, range: decided by [eq(test.p.relate_id, test.tr.id)], keep order:false, stats:pseudo desc select 1 as a from dual order by a limit 1; id count task operator info Projection_6 1.00 root 1 @@ -225,8 +225,8 @@ Limit_11 5.00 root offset:0, count:5 └─IndexMergeJoin_19 5.00 root inner join, inner:IndexReader_17, outer key:test.t1.a, inner key:test.t2.a ├─IndexReader_23 4.00 root index:IndexScan_22 │ └─IndexScan_22 4.00 cop table:t1, index:a, range:[NULL,+inf], keep order:false, stats:pseudo - └─IndexReader_17 10.00 root index:IndexScan_16 - └─IndexScan_16 10.00 cop table:t2, index:a, range: decided by [eq(test.t2.a, test.t1.a)], keep order:true, stats:pseudo + └─IndexReader_17 1.25 root index:IndexScan_16 + └─IndexScan_16 1.25 cop table:t2, index:a, range: decided by [eq(test.t2.a, test.t1.a)], keep order:true, stats:pseudo explain select /*+ TIDB_INLJ(t2) */ * from t t1 left join t t2 on t1.a = t2.a where t2.a is null limit 5; id count task operator info Limit_12 5.00 root offset:0, count:5 @@ -234,8 +234,8 @@ Limit_12 5.00 root offset:0, count:5 └─IndexMergeJoin_21 5.00 root left outer join, inner:IndexReader_19, outer key:test.t1.a, inner key:test.t2.a ├─IndexReader_25 4.00 root index:IndexScan_24 │ └─IndexScan_24 4.00 cop table:t1, index:a, range:[NULL,+inf], keep order:false, stats:pseudo - └─IndexReader_19 10.00 root index:IndexScan_18 - └─IndexScan_18 10.00 cop table:t2, index:a, range: decided by [eq(test.t2.a, test.t1.a)], keep order:true, stats:pseudo + └─IndexReader_19 1.25 root index:IndexScan_18 + └─IndexScan_18 1.25 cop table:t2, index:a, range: decided by [eq(test.t2.a, test.t1.a)], keep order:true, stats:pseudo explain select /*+ TIDB_SMJ(t1, t2) */ * from t t1 join t t2 on t1.a = t2.a limit 5; id count task operator info Limit_11 5.00 root offset:0, count:5 diff --git a/cmd/explaintest/r/tpch.result b/cmd/explaintest/r/tpch.result index e4da5801ab63c..a4dad5ab5de7e 100644 --- a/cmd/explaintest/r/tpch.result +++ b/cmd/explaintest/r/tpch.result @@ -184,8 +184,8 @@ limit 100; id count task operator info Projection_37 100.00 root tpch.supplier.s_acctbal, tpch.supplier.s_name, tpch.nation.n_name, tpch.part.p_partkey, tpch.part.p_mfgr, tpch.supplier.s_address, tpch.supplier.s_phone, tpch.supplier.s_comment └─TopN_40 100.00 root tpch.supplier.s_acctbal:desc, tpch.nation.n_name:asc, tpch.supplier.s_name:asc, tpch.part.p_partkey:asc, offset:0, count:100 - └─HashRightJoin_45 155496.00 root inner join, inner:HashLeftJoin_56, equal:[eq(tpch.part.p_partkey, tpch.partsupp.ps_partkey) eq(tpch.partsupp.ps_supplycost, min(ps_supplycost))] - ├─HashLeftJoin_56 155496.00 root inner join, inner:TableReader_84, equal:[eq(tpch.partsupp.ps_partkey, tpch.part.p_partkey)] + └─HashRightJoin_45 155496.00 root inner join, inner:IndexMergeJoin_55, equal:[eq(tpch.part.p_partkey, tpch.partsupp.ps_partkey) eq(tpch.partsupp.ps_supplycost, min(ps_supplycost))] + ├─IndexMergeJoin_55 155496.00 root inner join, inner:TableReader_53, outer key:tpch.partsupp.ps_partkey, inner key:tpch.part.p_partkey │ ├─HashRightJoin_59 8155010.44 root inner join, inner:HashRightJoin_61, equal:[eq(tpch.supplier.s_suppkey, tpch.partsupp.ps_suppkey)] │ │ ├─HashRightJoin_61 100000.00 root inner join, inner:HashRightJoin_72, equal:[eq(tpch.nation.n_nationkey, tpch.supplier.s_nationkey)] │ │ │ ├─HashRightJoin_72 5.00 root inner join, inner:TableReader_77, equal:[eq(tpch.region.r_regionkey, tpch.nation.n_regionkey)] @@ -198,9 +198,9 @@ Projection_37 100.00 root tpch.supplier.s_acctbal, tpch.supplier.s_name, tpch.na │ │ │ └─TableScan_78 500000.00 cop table:supplier, range:[-inf,+inf], keep order:false │ │ └─TableReader_81 40000000.00 root data:TableScan_80 │ │ └─TableScan_80 40000000.00 cop table:partsupp, range:[-inf,+inf], keep order:false - │ └─TableReader_84 155496.00 root data:Selection_83 - │ └─Selection_83 155496.00 cop eq(tpch.part.p_size, 30), like(tpch.part.p_type, "%STEEL", 92) - │ └─TableScan_82 10000000.00 cop table:part, range:[-inf,+inf], keep order:false + │ └─TableReader_53 0.02 root data:Selection_52 + │ └─Selection_52 0.02 cop eq(tpch.part.p_size, 30), like(tpch.part.p_type, "%STEEL", 92) + │ └─TableScan_51 0.02 cop table:part, range: decided by [tpch.partsupp.ps_partkey], keep order:true └─Selection_85 6524008.35 root not(isnull(min(ps_supplycost))) └─HashAgg_88 8155010.44 root group by:tpch.partsupp.ps_partkey, funcs:min(tpch.partsupp.ps_supplycost), firstrow(tpch.partsupp.ps_partkey) └─HashRightJoin_92 8155010.44 root inner join, inner:HashRightJoin_94, equal:[eq(tpch.supplier.s_suppkey, tpch.partsupp.ps_suppkey)] @@ -253,7 +253,7 @@ Projection_14 10.00 root tpch.lineitem.l_orderkey, 7_col_0, tpch.orders.o_orderd └─TopN_17 10.00 root 7_col_0:desc, tpch.orders.o_orderdate:asc, offset:0, count:10 └─HashAgg_23 40252367.98 root group by:col_4, col_5, col_6, funcs:sum(col_0), firstrow(col_1), firstrow(col_2), firstrow(col_3) └─Projection_74 91515927.49 root mul(tpch.lineitem.l_extendedprice, minus(1, tpch.lineitem.l_discount)), tpch.orders.o_orderdate, tpch.orders.o_shippriority, tpch.lineitem.l_orderkey, tpch.lineitem.l_orderkey, tpch.orders.o_orderdate, tpch.orders.o_shippriority - └─IndexMergeJoin_35 91515927.49 root inner join, inner:IndexLookUp_33, outer key:tpch.orders.o_orderkey, inner key:tpch.lineitem.l_orderkey + └─IndexJoin_29 91515927.49 root inner join, inner:IndexLookUp_28, outer key:tpch.orders.o_orderkey, inner key:tpch.lineitem.l_orderkey ├─HashRightJoin_64 22592975.51 root inner join, inner:TableReader_70, equal:[eq(tpch.customer.c_custkey, tpch.orders.o_custkey)] │ ├─TableReader_70 1498236.00 root data:Selection_69 │ │ └─Selection_69 1498236.00 cop eq(tpch.customer.c_mktsegment, "AUTOMOBILE") @@ -261,10 +261,10 @@ Projection_14 10.00 root tpch.lineitem.l_orderkey, 7_col_0, tpch.orders.o_orderd │ └─TableReader_67 36870000.00 root data:Selection_66 │ └─Selection_66 36870000.00 cop lt(tpch.orders.o_orderdate, 1995-03-13 00:00:00.000000) │ └─TableScan_65 75000000.00 cop table:orders, range:[-inf,+inf], keep order:false - └─IndexLookUp_33 0.54 root - ├─IndexScan_30 1.00 cop table:lineitem, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:true - └─Selection_32 0.54 cop gt(tpch.lineitem.l_shipdate, 1995-03-13 00:00:00.000000) - └─TableScan_31 1.00 cop table:lineitem, keep order:false + └─IndexLookUp_28 2.20 root + ├─IndexScan_25 4.05 cop table:lineitem, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:false + └─Selection_27 2.20 cop gt(tpch.lineitem.l_shipdate, 1995-03-13 00:00:00.000000) + └─TableScan_26 4.05 cop table:lineitem, keep order:false /* Q4 Order Priority Checking Query This query determines how well the order priority system is working and gives an assessment of customer satisfaction. @@ -298,14 +298,14 @@ id count task operator info Sort_10 1.00 root tpch.orders.o_orderpriority:asc └─Projection_12 1.00 root tpch.orders.o_orderpriority, 7_col_0 └─HashAgg_15 1.00 root group by:tpch.orders.o_orderpriority, funcs:count(1), firstrow(tpch.orders.o_orderpriority) - └─IndexMergeJoin_27 2340750.00 root semi join, inner:IndexLookUp_25, outer key:tpch.orders.o_orderkey, inner key:tpch.lineitem.l_orderkey + └─IndexJoin_21 2340750.00 root semi join, inner:IndexLookUp_20, outer key:tpch.orders.o_orderkey, inner key:tpch.lineitem.l_orderkey ├─TableReader_39 2925937.50 root data:Selection_38 │ └─Selection_38 2925937.50 cop ge(tpch.orders.o_orderdate, 1995-01-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1995-04-01) │ └─TableScan_37 75000000.00 cop table:orders, range:[-inf,+inf], keep order:false - └─IndexLookUp_25 0.80 root - ├─IndexScan_22 1.00 cop table:lineitem, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:true - └─Selection_24 0.80 cop lt(tpch.lineitem.l_commitdate, tpch.lineitem.l_receiptdate) - └─TableScan_23 1.00 cop table:lineitem, keep order:false + └─IndexLookUp_20 3.24 root + ├─IndexScan_17 4.05 cop table:lineitem, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:false + └─Selection_19 3.24 cop lt(tpch.lineitem.l_commitdate, tpch.lineitem.l_receiptdate) + └─TableScan_18 4.05 cop table:lineitem, keep order:false /* Q5 Local Supplier Volume Query This query lists the revenue volume done through local suppliers. @@ -348,7 +348,7 @@ Sort_23 5.00 root revenue:desc └─HashAgg_28 5.00 root group by:col_2, funcs:sum(col_0), firstrow(col_1) └─Projection_80 11822812.50 root mul(tpch.lineitem.l_extendedprice, minus(1, tpch.lineitem.l_discount)), tpch.nation.n_name, tpch.nation.n_name └─HashLeftJoin_36 11822812.50 root inner join, inner:TableReader_78, equal:[eq(tpch.supplier.s_nationkey, tpch.customer.c_nationkey) eq(tpch.orders.o_custkey, tpch.customer.c_custkey)] - ├─HashLeftJoin_48 11822812.50 root inner join, inner:TableReader_76, equal:[eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)] + ├─IndexMergeJoin_47 11822812.50 root inner join, inner:TableReader_45, outer key:tpch.lineitem.l_orderkey, inner key:tpch.orders.o_orderkey │ ├─HashRightJoin_51 61163763.01 root inner join, inner:HashRightJoin_53, equal:[eq(tpch.supplier.s_suppkey, tpch.lineitem.l_suppkey)] │ │ ├─HashRightJoin_53 100000.00 root inner join, inner:HashRightJoin_64, equal:[eq(tpch.nation.n_nationkey, tpch.supplier.s_nationkey)] │ │ │ ├─HashRightJoin_64 5.00 root inner join, inner:TableReader_69, equal:[eq(tpch.region.r_regionkey, tpch.nation.n_regionkey)] @@ -361,9 +361,9 @@ Sort_23 5.00 root revenue:desc │ │ │ └─TableScan_70 500000.00 cop table:supplier, range:[-inf,+inf], keep order:false │ │ └─TableReader_73 300005811.00 root data:TableScan_72 │ │ └─TableScan_72 300005811.00 cop table:lineitem, range:[-inf,+inf], keep order:false - │ └─TableReader_76 11822812.50 root data:Selection_75 - │ └─Selection_75 11822812.50 cop ge(tpch.orders.o_orderdate, 1994-01-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1995-01-01) - │ └─TableScan_74 75000000.00 cop table:orders, range:[-inf,+inf], keep order:false + │ └─TableReader_45 0.15 root data:Selection_44 + │ └─Selection_44 0.15 cop ge(tpch.orders.o_orderdate, 1994-01-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1995-01-01) + │ └─TableScan_43 0.19 cop table:orders, range: decided by [tpch.lineitem.l_orderkey], keep order:true └─TableReader_78 7500000.00 root data:TableScan_77 └─TableScan_77 7500000.00 cop table:customer, range:[-inf,+inf], keep order:false /* @@ -524,7 +524,7 @@ Sort_29 719.02 root all_nations.o_year:asc └─HashLeftJoin_43 563136.02 root inner join, inner:TableReader_110, equal:[eq(tpch.supplier.s_nationkey, tpch.n2.n_nationkey)] ├─HashLeftJoin_52 563136.02 root inner join, inner:TableReader_108, equal:[eq(tpch.lineitem.l_suppkey, tpch.supplier.s_suppkey)] │ ├─HashLeftJoin_63 563136.02 root inner join, inner:TableReader_106, equal:[eq(tpch.lineitem.l_partkey, tpch.part.p_partkey)] - │ │ ├─IndexMergeJoin_74 90788402.51 root inner join, inner:IndexLookUp_72, outer key:tpch.orders.o_orderkey, inner key:tpch.lineitem.l_orderkey + │ │ ├─IndexJoin_69 90788402.51 root inner join, inner:IndexLookUp_68, outer key:tpch.orders.o_orderkey, inner key:tpch.lineitem.l_orderkey │ │ │ ├─HashRightJoin_78 22413367.93 root inner join, inner:HashRightJoin_80, equal:[eq(tpch.customer.c_custkey, tpch.orders.o_custkey)] │ │ │ │ ├─HashRightJoin_80 1500000.00 root inner join, inner:HashRightJoin_91, equal:[eq(tpch.n1.n_nationkey, tpch.customer.c_nationkey)] │ │ │ │ │ ├─HashRightJoin_91 5.00 root inner join, inner:TableReader_96, equal:[eq(tpch.region.r_regionkey, tpch.n1.n_regionkey)] @@ -538,9 +538,9 @@ Sort_29 719.02 root all_nations.o_year:asc │ │ │ │ └─TableReader_101 22413367.93 root data:Selection_100 │ │ │ │ └─Selection_100 22413367.93 cop ge(tpch.orders.o_orderdate, 1995-01-01 00:00:00.000000), le(tpch.orders.o_orderdate, 1996-12-31 00:00:00.000000) │ │ │ │ └─TableScan_99 75000000.00 cop table:orders, range:[-inf,+inf], keep order:false - │ │ │ └─IndexLookUp_72 1.00 root - │ │ │ ├─IndexScan_70 1.00 cop table:lineitem, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:true - │ │ │ └─TableScan_71 1.00 cop table:lineitem, keep order:false + │ │ │ └─IndexLookUp_68 4.05 root + │ │ │ ├─IndexScan_66 4.05 cop table:lineitem, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:false + │ │ │ └─TableScan_67 4.05 cop table:lineitem, keep order:false │ │ └─TableReader_106 61674.00 root data:Selection_105 │ │ └─Selection_105 61674.00 cop eq(tpch.part.p_type, "SMALL PLATED COPPER") │ │ └─TableScan_104 10000000.00 cop table:part, range:[-inf,+inf], keep order:false @@ -672,10 +672,10 @@ Projection_17 20.00 root tpch.customer.c_custkey, tpch.customer.c_name, 9_col_0, │ └─TableReader_58 3017307.69 root data:Selection_57 │ └─Selection_57 3017307.69 cop ge(tpch.orders.o_orderdate, 1993-08-01 00:00:00.000000), lt(tpch.orders.o_orderdate, 1993-11-01) │ └─TableScan_56 75000000.00 cop table:orders, range:[-inf,+inf], keep order:false - └─IndexLookUp_36 0.25 root - ├─IndexScan_33 1.00 cop table:lineitem, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:true - └─Selection_35 0.25 cop eq(tpch.lineitem.l_returnflag, "R") - └─TableScan_34 1.00 cop table:lineitem, keep order:false + └─IndexLookUp_36 1.00 root + ├─IndexScan_33 4.05 cop table:lineitem, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:true + └─Selection_35 1.00 cop eq(tpch.lineitem.l_returnflag, "R") + └─TableScan_34 4.05 cop table:lineitem, keep order:false /* Q11 Important Stock Identification Query This query finds the most important subset of suppliers' stock in a given nation. @@ -935,8 +935,8 @@ Sort_13 3863988.24 root supplier_cnt:desc, tpch.part.p_brand:asc, tpch.part.p_ty │ ├─TableReader_55 1200618.43 root data:Selection_54 │ │ └─Selection_54 1200618.43 cop in(tpch.part.p_size, 48, 19, 12, 4, 41, 7, 21, 39), ne(tpch.part.p_brand, "Brand#34"), not(like(tpch.part.p_type, "LARGE BRUSHED%", 92)) │ │ └─TableScan_53 10000000.00 cop table:part, range:[-inf,+inf], keep order:false - │ └─IndexReader_34 1.00 root index:IndexScan_33 - │ └─IndexScan_33 1.00 cop table:partsupp, index:PS_PARTKEY, PS_SUPPKEY, range: decided by [eq(tpch.partsupp.ps_partkey, tpch.part.p_partkey)], keep order:true + │ └─IndexReader_34 4.02 root index:IndexScan_33 + │ └─IndexScan_33 4.02 cop table:partsupp, index:PS_PARTKEY, PS_SUPPKEY, range: decided by [eq(tpch.partsupp.ps_partkey, tpch.part.p_partkey)], keep order:true └─TableReader_62 400000.00 root data:Selection_61 └─Selection_61 400000.00 cop like(tpch.supplier.s_comment, "%Customer%Complaints%", 92) └─TableScan_60 500000.00 cop table:supplier, range:[-inf,+inf], keep order:false @@ -1029,7 +1029,7 @@ id count task operator info Projection_24 100.00 root tpch.customer.c_name, tpch.customer.c_custkey, tpch.orders.o_orderkey, tpch.orders.o_orderdate, tpch.orders.o_totalprice, 14_col_0 └─TopN_27 100.00 root tpch.orders.o_totalprice:desc, tpch.orders.o_orderdate:asc, offset:0, count:100 └─HashAgg_33 59251097.60 root group by:tpch.customer.c_custkey, tpch.customer.c_name, tpch.orders.o_orderdate, tpch.orders.o_orderkey, tpch.orders.o_totalprice, funcs:sum(tpch.lineitem.l_quantity), firstrow(tpch.customer.c_custkey), firstrow(tpch.customer.c_name), firstrow(tpch.orders.o_orderkey), firstrow(tpch.orders.o_totalprice), firstrow(tpch.orders.o_orderdate) - └─IndexMergeJoin_43 240004648.80 root inner join, inner:IndexLookUp_41, outer key:tpch.orders.o_orderkey, inner key:tpch.lineitem.l_orderkey + └─HashRightJoin_45 240004648.80 root inner join, inner:HashLeftJoin_46, equal:[eq(tpch.orders.o_orderkey, tpch.lineitem.l_orderkey)] ├─HashLeftJoin_46 59251097.60 root inner join, inner:Selection_61, equal:[eq(tpch.orders.o_orderkey, tpch.lineitem.l_orderkey)] │ ├─HashRightJoin_56 75000000.00 root inner join, inner:TableReader_60, equal:[eq(tpch.customer.c_custkey, tpch.orders.o_custkey)] │ │ ├─TableReader_60 7500000.00 root data:TableScan_59 @@ -1041,9 +1041,8 @@ Projection_24 100.00 root tpch.customer.c_name, tpch.customer.c_custkey, tpch.or │ └─TableReader_69 74063872.00 root data:HashAgg_62 │ └─HashAgg_62 74063872.00 cop group by:tpch.lineitem.l_orderkey, funcs:sum(tpch.lineitem.l_quantity) │ └─TableScan_67 300005811.00 cop table:lineitem, range:[-inf,+inf], keep order:false - └─IndexLookUp_41 1.00 root - ├─IndexScan_39 1.00 cop table:lineitem, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.lineitem.l_orderkey, tpch.orders.o_orderkey)], keep order:true - └─TableScan_40 1.00 cop table:lineitem, keep order:false + └─TableReader_77 300005811.00 root data:TableScan_76 + └─TableScan_76 300005811.00 cop table:lineitem, range:[-inf,+inf], keep order:false /* Q19 Discounted Revenue Query The Discounted Revenue Query reports the gross discounted revenue attributed to the sale of selected parts handled @@ -1164,9 +1163,9 @@ Sort_28 20000.00 root tpch.supplier.s_name:asc │ ├─TableReader_90 80007.93 root data:Selection_89 │ │ └─Selection_89 80007.93 cop like(tpch.part.p_name, "green%", 92) │ │ └─TableScan_88 10000000.00 cop table:part, range:[-inf,+inf], keep order:false - │ └─IndexLookUp_67 1.00 root - │ ├─IndexScan_65 1.00 cop table:partsupp, index:PS_PARTKEY, PS_SUPPKEY, range: decided by [eq(tpch.partsupp.ps_partkey, tpch.part.p_partkey)], keep order:true - │ └─TableScan_66 1.00 cop table:partsupp, keep order:false + │ └─IndexLookUp_67 4.02 root + │ ├─IndexScan_65 4.02 cop table:partsupp, index:PS_PARTKEY, PS_SUPPKEY, range: decided by [eq(tpch.partsupp.ps_partkey, tpch.part.p_partkey)], keep order:true + │ └─TableScan_66 4.02 cop table:partsupp, keep order:false └─TableReader_95 44189356.65 root data:Selection_94 └─Selection_94 44189356.65 cop ge(tpch.lineitem.l_shipdate, 1993-01-01 00:00:00.000000), lt(tpch.lineitem.l_shipdate, 1994-01-01) └─TableScan_93 300005811.00 cop table:lineitem, range:[-inf,+inf], keep order:false @@ -1222,8 +1221,8 @@ id count task operator info Projection_25 1.00 root tpch.supplier.s_name, 17_col_0 └─TopN_28 1.00 root 17_col_0:desc, tpch.supplier.s_name:asc, offset:0, count:100 └─HashAgg_34 1.00 root group by:tpch.supplier.s_name, funcs:count(1), firstrow(tpch.supplier.s_name) - └─IndexMergeJoin_46 7828961.66 root anti semi join, inner:IndexLookUp_44, outer key:tpch.l1.l_orderkey, inner key:tpch.l3.l_orderkey, other cond:ne(tpch.l3.l_suppkey, tpch.l1.l_suppkey), ne(tpch.l3.l_suppkey, tpch.supplier.s_suppkey) - ├─IndexMergeJoin_77 9786202.08 root semi join, inner:IndexLookUp_75, outer key:tpch.l1.l_orderkey, inner key:tpch.l2.l_orderkey, other cond:ne(tpch.l2.l_suppkey, tpch.l1.l_suppkey), ne(tpch.l2.l_suppkey, tpch.supplier.s_suppkey) + └─IndexJoin_40 7828961.66 root anti semi join, inner:IndexLookUp_39, outer key:tpch.l1.l_orderkey, inner key:tpch.l3.l_orderkey, other cond:ne(tpch.l3.l_suppkey, tpch.l1.l_suppkey), ne(tpch.l3.l_suppkey, tpch.supplier.s_suppkey) + ├─IndexJoin_72 9786202.08 root semi join, inner:IndexLookUp_71, outer key:tpch.l1.l_orderkey, inner key:tpch.l2.l_orderkey, other cond:ne(tpch.l2.l_suppkey, tpch.l1.l_suppkey), ne(tpch.l2.l_suppkey, tpch.supplier.s_suppkey) │ ├─IndexMergeJoin_88 12232752.60 root inner join, inner:TableReader_86, outer key:tpch.l1.l_orderkey, inner key:tpch.orders.o_orderkey │ │ ├─HashRightJoin_92 12232752.60 root inner join, inner:HashRightJoin_103, equal:[eq(tpch.supplier.s_suppkey, tpch.l1.l_suppkey)] │ │ │ ├─HashRightJoin_103 20000.00 root inner join, inner:TableReader_108, equal:[eq(tpch.nation.n_nationkey, tpch.supplier.s_nationkey)] @@ -1238,13 +1237,13 @@ Projection_25 1.00 root tpch.supplier.s_name, 17_col_0 │ │ └─TableReader_86 0.80 root data:Selection_85 │ │ └─Selection_85 0.80 cop eq(tpch.orders.o_orderstatus, "F") │ │ └─TableScan_84 1.00 cop table:orders, range: decided by [tpch.l1.l_orderkey], keep order:true - │ └─IndexLookUp_75 1.00 root - │ ├─IndexScan_73 1.00 cop table:l2, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.l2.l_orderkey, tpch.l1.l_orderkey)], keep order:true - │ └─TableScan_74 1.00 cop table:l2, keep order:false - └─IndexLookUp_44 0.80 root - ├─IndexScan_41 1.00 cop table:l3, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.l3.l_orderkey, tpch.l1.l_orderkey)], keep order:true - └─Selection_43 0.80 cop gt(tpch.l3.l_receiptdate, tpch.l3.l_commitdate) - └─TableScan_42 1.00 cop table:l3, keep order:false + │ └─IndexLookUp_71 4.05 root + │ ├─IndexScan_69 4.05 cop table:l2, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.l2.l_orderkey, tpch.l1.l_orderkey)], keep order:false + │ └─TableScan_70 4.05 cop table:l2, keep order:false + └─IndexLookUp_39 3.24 root + ├─IndexScan_36 4.05 cop table:l3, index:L_ORDERKEY, L_LINENUMBER, range: decided by [eq(tpch.l3.l_orderkey, tpch.l1.l_orderkey)], keep order:false + └─Selection_38 3.24 cop gt(tpch.l3.l_receiptdate, tpch.l3.l_commitdate) + └─TableScan_37 4.05 cop table:l3, keep order:false /* Q22 Global Sales Opportunity Query The Global Sales Opportunity Query identifies geographies where there are customers who may be likely to make a diff --git a/planner/core/cbo_test.go b/planner/core/cbo_test.go index 52223d513a51e..3512cc423b2eb 100644 --- a/planner/core/cbo_test.go +++ b/planner/core/cbo_test.go @@ -905,9 +905,9 @@ func (s *testAnalyzeSuite) TestIssue9562(c *C) { "├─TableReader_17 9980.01 root data:Selection_16", "│ └─Selection_16 9980.01 cop not(isnull(test.t1.a)), not(isnull(test.t1.c))", "│ └─TableScan_15 10000.00 cop table:t1, range:[-inf,+inf], keep order:false, stats:pseudo", - "└─IndexReader_12 9.98 root index:Selection_11", - " └─Selection_11 9.98 cop not(isnull(test.t2.a)), not(isnull(test.t2.c))", - " └─IndexScan_10 10.00 cop table:t2, index:a, b, c, range: decided by [eq(test.t2.a, test.t1.a) gt(test.t2.b, minus(test.t1.b, 1)) lt(test.t2.b, plus(test.t1.b, 1))], keep order:true, stats:pseudo", + "└─IndexReader_12 1.25 root index:Selection_11", + " └─Selection_11 1.25 cop not(isnull(test.t2.a)), not(isnull(test.t2.c))", + " └─IndexScan_10 1.25 cop table:t2, index:a, b, c, range: decided by [eq(test.t2.a, test.t1.a) gt(test.t2.b, minus(test.t1.b, 1)) lt(test.t2.b, plus(test.t1.b, 1))], keep order:true, stats:pseudo", )) tk.MustExec("create table t(a int, b int, index idx_ab(a, b))") @@ -953,35 +953,8 @@ func (s *testAnalyzeSuite) TestIssue9805(c *C) { d int not null unique auto_increment ) `) - rs := tk.MustQuery("explain analyze select t1.id, t2.a from t1 join t2 on t1.a = t2.d where t1.b = 't2' and t1.d = 4") - - // Expected output is like: - // - // +--------------------------------+----------+------+-------------------------------------------------------------------------------------------------+----------------------------------+---------------+ - // | id | count | task | operator info | execution info | memory | - // +--------------------------------+----------+------+-------------------------------------------------------------------------------------------------+----------------------------------+---------------+ - // | Projection_9 | 10.00 | root | test.t1.id, test.t2.a | time:0s, loops:0, rows:0 | N/A | - // | └─IndexJoin_13 | 10.00 | root | inner join, inner:IndexLookUp_12, outer key:test.t1.a, inner key:test.t2.d | time:275.903µs, loops:1, rows:0 | 1.57421875 KB | - // | ├─Projection_21 | 8.00 | root | test.t1.id, test.t1.a, test.t1.b, cast(mod(test.t1.a, 30)) | time:23.811µs, loops:1, rows:0 | N/A | - // | │ └─Selection_22 | 8.00 | root | eq(cast(mod(test.t1.a, 30)), 4) | time:18.658µs, loops:1, rows:0 | N/A | - // | │ └─TableReader_25 | 10.00 | root | data:Selection_24 | time:15.488µs, loops:1, rows:0 | 117 Bytes | - // | │ └─Selection_24 | 10.00 | cop | eq(test.t1.b, "t2") | time:21.872µs, loops:1, rows:0 | N/A | - // | │ └─TableScan_23 | 10000.00 | cop | table:t1, range:[-inf,+inf], keep order:false, stats:pseudo | time:20.79µs, loops:1, rows:0 | N/A | - // | └─IndexLookUp_12 | 10.00 | root | | time:0ns, loops:0, rows:0 | N/A | - // | ├─IndexScan_10 | 10.00 | cop | table:t2, index:d, range: decided by [eq(test.t2.d, test.t1.a)], keep order:false, stats:pseudo | time:0ns, loops:0, rows:0 | N/A | - // | └─TableScan_11 | 10.00 | cop | table:t2, keep order:false, stats:pseudo | time:0ns, loops:0, rows:0 | N/A | - // +--------------------------------+----------+------+-------------------------------------------------------------------------------------------------+----------------------------------+---------------+ - // - c.Assert(rs.Rows(), HasLen, 10) - hasIndexLookUp12 := false - for _, row := range rs.Rows() { - c.Assert(row, HasLen, 6) - if strings.HasSuffix(row[0].(string), "IndexLookUp_12") { - hasIndexLookUp12 = true - c.Assert(row[4], Equals, "time:0ns, loops:0, rows:0") - } - } - c.Assert(hasIndexLookUp12, IsTrue) + // Test when both tables are empty, EXPLAIN ANALYZE for IndexLookUp would not panic. + tk.MustExec("explain analyze select /*+ TIDB_INLJ(t2) */ t1.id, t2.a from t1 join t2 on t1.a = t2.d where t1.b = 't2' and t1.d = 4") } func (s *testAnalyzeSuite) TestLimitCrossEstimation(c *C) { diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index b95a68a728f23..0502a3fe2e37d 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -426,7 +426,7 @@ func (p *LogicalJoin) constructIndexMergeJoin( // Then, we will extract the join keys of p's equal conditions. Then check whether all of them are just the primary key // or match some part of on index. If so we will choose the best one and construct a index join. func (p *LogicalJoin) getIndexJoinByOuterIdx(prop *property.PhysicalProperty, outerIdx int) []PhysicalPlan { - innerChild := p.children[1-outerIdx] + outerChild, innerChild := p.children[outerIdx], p.children[1-outerIdx] var ( innerJoinKeys []*expression.Column outerJoinKeys []*expression.Column @@ -450,6 +450,10 @@ func (p *LogicalJoin) getIndexJoinByOuterIdx(prop *property.PhysicalProperty, ou return nil } } + var avgInnerRowCnt float64 + if outerChild.statsInfo().RowCount > 0 { + avgInnerRowCnt = p.equalCondOutCnt / outerChild.statsInfo().RowCount + } var tblPath *accessPath for _, path := range ds.possibleAccessPaths { if path.isTablePath { @@ -471,11 +475,11 @@ func (p *LogicalJoin) getIndexJoinByOuterIdx(prop *property.PhysicalProperty, ou if pkMatched { joins := make([]PhysicalPlan, 0, 2) - innerTask := p.constructInnerTableScanTask(ds, pkCol, outerJoinKeys, us, false) + innerTask := p.constructInnerTableScanTask(ds, pkCol, outerJoinKeys, us, false, avgInnerRowCnt) joins = append(joins, p.constructIndexJoin(prop, outerIdx, innerTask, nil, keyOff2IdxOff, nil, nil)...) // The index merge join's inner plan is different from index join, so we should consturct another inner plan // for it. - innerTask2 := p.constructInnerTableScanTask(ds, pkCol, outerJoinKeys, us, true) + innerTask2 := p.constructInnerTableScanTask(ds, pkCol, outerJoinKeys, us, true, avgInnerRowCnt) joins = append(joins, p.constructIndexMergeJoin(prop, outerIdx, innerTask2, nil, keyOff2IdxOff, nil, nil)...) // Since the primary key means one value corresponding to exact one row, this will always be a no worse one // comparing to other index. @@ -507,12 +511,12 @@ func (p *LogicalJoin) getIndexJoinByOuterIdx(prop *property.PhysicalProperty, ou } joins := make([]PhysicalPlan, 0, 2) rangeInfo := helper.buildRangeDecidedByInformation(helper.chosenPath.idxCols, outerJoinKeys) - innerTask := p.constructInnerIndexScanTask(ds, helper.chosenPath, helper.chosenRemained, outerJoinKeys, us, rangeInfo, false) + innerTask := p.constructInnerIndexScanTask(ds, helper.chosenPath, helper.chosenRemained, outerJoinKeys, us, rangeInfo, false, avgInnerRowCnt) joins = append(joins, p.constructIndexJoin(prop, outerIdx, innerTask, helper.chosenRanges, keyOff2IdxOff, helper.chosenPath, helper.lastColManager)...) // The index merge join's inner plan is different from index join, so we should consturct another inner plan // for it. - innerTask2 := p.constructInnerIndexScanTask(ds, helper.chosenPath, helper.chosenRemained, outerJoinKeys, us, rangeInfo, true) + innerTask2 := p.constructInnerIndexScanTask(ds, helper.chosenPath, helper.chosenRemained, outerJoinKeys, us, rangeInfo, true, avgInnerRowCnt) joins = append(joins, p.constructIndexMergeJoin(prop, outerIdx, innerTask2, helper.chosenRanges, keyOff2IdxOff, helper.chosenPath, helper.lastColManager)...) return joins } @@ -564,7 +568,14 @@ func (ijHelper *indexJoinBuildHelper) buildRangeDecidedByInformation(idxCols []* } // constructInnerTableScanTask is specially used to construct the inner plan for PhysicalIndexJoin. -func (p *LogicalJoin) constructInnerTableScanTask(ds *DataSource, pk *expression.Column, outerJoinKeys []*expression.Column, us *LogicalUnionScan, keepOrder bool) task { +func (p *LogicalJoin) constructInnerTableScanTask( + ds *DataSource, + pk *expression.Column, + outerJoinKeys []*expression.Column, + us *LogicalUnionScan, + keepOrder bool, + rowCount float64, +) task { ranges := ranger.FullIntRange(mysql.HasUnsignedFlag(pk.RetType.Flag)) ts := PhysicalTableScan{ Table: ds.tableInfo, @@ -579,7 +590,7 @@ func (p *LogicalJoin) constructInnerTableScanTask(ds *DataSource, pk *expression ts.SetSchema(ds.schema) ts.stats = &property.StatsInfo{ // TableScan as inner child of IndexJoin can return at most 1 tuple for each outer row. - RowCount: 1, + RowCount: math.Min(1.0, rowCount), StatsVersion: ds.stats.StatsVersion, // Cardinality would not be used in cost computation of IndexJoin, set leave it as default nil. } @@ -625,6 +636,7 @@ func (p *LogicalJoin) constructInnerIndexScanTask( us *LogicalUnionScan, rangeInfo string, keepOrder bool, + rowCount float64, ) task { is := PhysicalIndexScan{ Table: ds.tableInfo, @@ -639,22 +651,6 @@ func (p *LogicalJoin) constructInnerIndexScanTask( Ranges: ranger.FullRange(), rangeInfo: rangeInfo, }.Init(ds.ctx) - - var rowCount float64 - idxHist, ok := ds.statisticTable.Indices[path.index.ID] - // TODO: we are assuming that: - // - rows are uniformly distributed among the distinct values; - // - every outer row can find matches in inner table; - // The second assumption is too strong, we'd better analyze histograms - // of both sides to compute a factor we should multiply to the current - // estimated `rowCount`. - // We can improve this after https://github.com/pingcap/tidb/pull/8097 - // is merged, since it provides some utilities we need. - if ok && !ds.statisticTable.Pseudo { - rowCount = idxHist.AvgCountPerNotNullValue(ds.statisticTable.Count) - } else { - rowCount = ds.statisticTable.PseudoAvgCountPerValue() - } is.stats = ds.tableStats.ScaleByExpectCnt(rowCount) cop := &copTask{ indexPlan: is, diff --git a/planner/core/physical_plan_test.go b/planner/core/physical_plan_test.go index 2e74ada83c752..bf8aa80cbca54 100644 --- a/planner/core/physical_plan_test.go +++ b/planner/core/physical_plan_test.go @@ -497,7 +497,7 @@ func (s *testPlanSuite) TestIndexJoinUnionScan(c *C) { // Test Index Join + UnionScan + IndexScan. { sql: "select /*+ TIDB_INLJ(t1, t2) */ t1.a , t2.c from t t1, t t2 where t1.a = t2.c", - best: "IndexMergeJoin{TableReader(Table(t))->UnionScan([])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])->UnionScan([])}(test.t2.c,test.t1.a)->Projection", + best: "IndexMergeJoin{IndexReader(Index(t.f)[[NULL,+inf]])->UnionScan([])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])->UnionScan([])}(test.t1.a,test.t2.c)->Projection", is: s.is, }, // Index Join + Union Scan + Union All is not supported now. diff --git a/planner/core/testdata/plan_suite_out.json b/planner/core/testdata/plan_suite_out.json index adcca36bf931c..d750c6995f59a 100644 --- a/planner/core/testdata/plan_suite_out.json +++ b/planner/core/testdata/plan_suite_out.json @@ -297,7 +297,7 @@ }, { "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,+inf]], Table(t))}(test.t1.a,test.t2.c)" + "Best": "IndexMergeJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t1.a,test.t2.c)" }, { "SQL": "select /*+ TIDB_INLJ(t2) */ t1.a , t2.a from t t1, t t2 where t1.a = t2.c", @@ -321,7 +321,7 @@ }, { "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 join t t2 on t1.d=t2.d and t2.c = 1", - "Best": "IndexJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t1.d,test.t2.d)" + "Best": "IndexMergeJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t1.d,test.t2.d)" }, { "SQL": "select /*+ TIDB_INLJ(t1, t2) */ * from t t1 left outer join t t2 on t1.a = t2.b", @@ -341,7 +341,7 @@ }, { "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,+inf]], Table(t))}(test.t1.c,test.t2.c)" + "Best": "IndexMergeJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t1.c,test.t2.c)" }, { "SQL": "select /*+ TIDB_INLJ(t2) */ * from t t1 join t t2 where t1.a = t2.a and t1.f=t2.f", @@ -464,7 +464,7 @@ }, { "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,+inf]], Table(t))}(test.t1.c,test.t2.c)->Delete" + "Best": "IndexMergeJoin{TableReader(Table(t))->IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))}(test.t1.c,test.t2.c)->Delete" }, { "SQL": "delete /*+ TIDB_SMJ(t1, t2) */ from t1 using t t1, t t2 where t1.c=t2.c",