Skip to content

Commit 9d69b7c

Browse files
authored
planner: fix wrong HashAgg estrows for inner operator of index join (#60071) (#60336)
close #59902
1 parent 8fdf6a5 commit 9d69b7c

File tree

6 files changed

+56
-29
lines changed

6 files changed

+56
-29
lines changed

pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,9 +1711,9 @@
17111711
"IndexJoin 9990.00 root inner join, inner:HashAgg, outer key:test.t1.a, inner key:test.t2.a, equal cond:eq(test.t1.a, test.t2.a)",
17121712
"├─TableReader(Build) 10000.00 root data:TableFullScan",
17131713
"│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
1714-
"└─HashAgg(Probe) 79920000.00 root group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a",
1715-
" └─IndexReader 79920000.00 root index:HashAgg",
1716-
" └─HashAgg 79920000.00 cop[tikv] group by:test.t2.a, ",
1714+
"└─HashAgg(Probe) 9990.00 root group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a",
1715+
" └─IndexReader 9990.00 root index:HashAgg",
1716+
" └─HashAgg 9990.00 cop[tikv] group by:test.t2.a, ",
17171717
" └─Selection 9990.00 cop[tikv] not(isnull(test.t2.a))",
17181718
" └─IndexRangeScan 10000.00 cop[tikv] table:t2, index:ia(a) range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo"
17191719
],

pkg/planner/core/exhaust_physical_plans.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,12 @@ func constructIndexJoinInnerSideTaskWithAggCheck(p *logicalop.LogicalJoin, prop
13991399
// build physical agg and attach to task
14001400
var aggTask base.Task
14011401
// build stream agg and change ds keep order to true
1402+
stats := la.StatsInfo()
1403+
if dsCopTask.indexPlan != nil {
1404+
stats = stats.ScaleByExpectCnt(dsCopTask.indexPlan.StatsInfo().RowCount)
1405+
} else if dsCopTask.tablePlan != nil {
1406+
stats = stats.ScaleByExpectCnt(dsCopTask.tablePlan.StatsInfo().RowCount)
1407+
}
14021408
if preferStream {
14031409
newGbyItems := make([]expression.Expression, len(la.GroupByItems))
14041410
copy(newGbyItems, la.GroupByItems)
@@ -1419,14 +1425,15 @@ func constructIndexJoinInnerSideTaskWithAggCheck(p *logicalop.LogicalJoin, prop
14191425
if physicalIndexScan != nil {
14201426
physicalIndexScan.KeepOrder = true
14211427
dsCopTask.keepOrder = true
1428+
streamAgg.SetStats(stats)
14221429
aggTask = streamAgg.Attach2Task(dsCopTask)
14231430
}
14241431
}
14251432
}
14261433

14271434
// build hash agg, when the stream agg is illegal such as the order by prop is not matched
14281435
if aggTask == nil {
1429-
physicalHashAgg := NewPhysicalHashAgg(la, la.StatsInfo(), prop)
1436+
physicalHashAgg := NewPhysicalHashAgg(la, stats, prop)
14301437
physicalHashAgg.SetSchema(la.Schema().Clone())
14311438
aggTask = physicalHashAgg.Attach2Task(dsCopTask)
14321439
}

pkg/planner/core/issuetest/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ go_test(
1010
data = glob(["testdata/**"]),
1111
flaky = True,
1212
race = "on",
13-
shard_count = 7,
13+
shard_count = 8,
1414
deps = [
1515
"//pkg/parser",
1616
"//pkg/planner",

pkg/planner/core/issuetest/planner_issue_test.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,11 @@ func TestIssue54535(t *testing.T) {
107107
" ├─TableReader_43(Build) 9990.00 root data:Selection_42",
108108
" │ └─Selection_42 9990.00 cop[tikv] not(isnull(test.ta.a1))",
109109
" │ └─TableFullScan_41 10000.00 cop[tikv] table:ta keep order:false, stats:pseudo",
110-
" └─HashAgg_14(Probe) 79840080.00 root group by:test.tb.b1, test.tb.b2, funcs:count(Column#11)->Column#9, funcs:firstrow(test.tb.b1)->test.tb.b1",
111-
" └─IndexLookUp_15 79840080.00 root ",
110+
" └─HashAgg_14(Probe) 9990.00 root group by:test.tb.b1, test.tb.b2, funcs:count(Column#11)->Column#9, funcs:firstrow(test.tb.b1)->test.tb.b1",
111+
" └─IndexLookUp_15 9990.00 root ",
112112
" ├─Selection_12(Build) 9990.00 cop[tikv] not(isnull(test.tb.b1))",
113113
" │ └─IndexRangeScan_10 10000.00 cop[tikv] table:tb, index:idx_b(b1) range: decided by [eq(test.tb.b1, test.ta.a1)], keep order:false, stats:pseudo",
114-
" └─HashAgg_13(Probe) 79840080.00 cop[tikv] group by:test.tb.b1, test.tb.b2, funcs:count(test.tb.b3)->Column#11",
114+
" └─HashAgg_13(Probe) 9990.00 cop[tikv] group by:test.tb.b1, test.tb.b2, funcs:count(test.tb.b3)->Column#11",
115115
" └─TableRowIDScan_11 9990.00 cop[tikv] table:tb keep order:false, stats:pseudo"))
116116
// test for issues/55169
117117
tk.MustExec("create table t1(col_1 int, index idx_1(col_1));")
@@ -231,3 +231,22 @@ ON base.c1 <=> base2.c1;`).Sort().Check(testkit.Rows(
231231
"1 Alice 1 100",
232232
"<nil> Bob <nil> <nil>"))
233233
}
234+
235+
func TestIssue59902(t *testing.T) {
236+
store := testkit.CreateMockStore(t)
237+
tk := testkit.NewTestKit(t, store)
238+
tk.MustExec("use test;")
239+
tk.MustExec("create table t1(a int primary key, b int);")
240+
tk.MustExec("create table t2(a int, b int, key idx(a));")
241+
tk.MustExec("set tidb_enable_inl_join_inner_multi_pattern=on;")
242+
tk.MustQuery("explain format='brief' select t1.b,(select count(*) from t2 where t2.a=t1.a) as a from t1 where t1.a=1;").
243+
Check(testkit.Rows(
244+
"Projection 1.00 root test.t1.b, ifnull(Column#9, 0)->Column#9",
245+
"└─IndexJoin 1.00 root left outer join, inner:HashAgg, outer key:test.t1.a, inner key:test.t2.a, equal cond:eq(test.t1.a, test.t2.a)",
246+
" ├─Point_Get(Build) 1.00 root table:t1 handle:1",
247+
" └─HashAgg(Probe) 1.00 root group by:test.t2.a, funcs:count(Column#10)->Column#9, funcs:firstrow(test.t2.a)->test.t2.a",
248+
" └─IndexReader 1.00 root index:HashAgg",
249+
" └─HashAgg 1.00 cop[tikv] group by:test.t2.a, funcs:count(1)->Column#10",
250+
" └─Selection 1.00 cop[tikv] not(isnull(test.t2.a))",
251+
" └─IndexRangeScan 1.00 cop[tikv] table:t2, index:idx(a) range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo"))
252+
}

tests/integrationtest/r/planner/core/casetest/physicalplantest/physical_plan.result

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3195,16 +3195,17 @@ show warnings;
31953195
Level Code Message
31963196
explain format = 'brief' SELECT ta.NAME,(SELECT sum(tb.CODE) FROM tb WHERE ta.id = tb.id) tb_sum_code FROM ta WHERE ta.NAME LIKE 'chad999%';
31973197
id estRows task access object operator info
3198-
HashJoin 250.00 root left outer join, equal:[eq(planner__core__casetest__physicalplantest__physical_plan.ta.id, planner__core__casetest__physicalplantest__physical_plan.tb.id)]
3198+
IndexHashJoin 250.00 root left outer join, inner:HashAgg, outer key:planner__core__casetest__physicalplantest__physical_plan.ta.id, inner key:planner__core__casetest__physicalplantest__physical_plan.tb.id, equal cond:eq(planner__core__casetest__physicalplantest__physical_plan.ta.id, planner__core__casetest__physicalplantest__physical_plan.tb.id)
31993199
├─IndexLookUp(Build) 250.00 root
32003200
│ ├─Selection(Build) 250.00 cop[tikv] like(planner__core__casetest__physicalplantest__physical_plan.ta.name, "chad999%", 92)
32013201
│ │ └─IndexRangeScan 250.00 cop[tikv] table:ta, index:idx_ta_name(name) range:["chad999","chad99:"), keep order:false, stats:pseudo
32023202
│ └─TableRowIDScan(Probe) 250.00 cop[tikv] table:ta keep order:false, stats:pseudo
3203-
└─HashAgg(Probe) 7992.00 root group by:planner__core__casetest__physicalplantest__physical_plan.tb.id, funcs:sum(Column#26)->Column#13, funcs:firstrow(planner__core__casetest__physicalplantest__physical_plan.tb.id)->planner__core__casetest__physicalplantest__physical_plan.tb.id
3204-
└─TableReader 7992.00 root data:HashAgg
3205-
└─HashAgg 7992.00 cop[tikv] group by:planner__core__casetest__physicalplantest__physical_plan.tb.id, funcs:sum(planner__core__casetest__physicalplantest__physical_plan.tb.code)->Column#26
3206-
└─Selection 9990.00 cop[tikv] not(isnull(planner__core__casetest__physicalplantest__physical_plan.tb.id))
3207-
└─TableFullScan 10000.00 cop[tikv] table:tb keep order:false, stats:pseudo
3203+
└─HashAgg(Probe) 250.00 root group by:planner__core__casetest__physicalplantest__physical_plan.tb.id, funcs:sum(Column#15)->Column#13, funcs:firstrow(planner__core__casetest__physicalplantest__physical_plan.tb.id)->planner__core__casetest__physicalplantest__physical_plan.tb.id
3204+
└─IndexLookUp 250.00 root
3205+
├─Selection(Build) 250.00 cop[tikv] not(isnull(planner__core__casetest__physicalplantest__physical_plan.tb.id))
3206+
│ └─IndexRangeScan 250.25 cop[tikv] table:tb, index:idx_tb_id(id) range: decided by [eq(planner__core__casetest__physicalplantest__physical_plan.tb.id, planner__core__casetest__physicalplantest__physical_plan.ta.id)], keep order:false, stats:pseudo
3207+
└─HashAgg(Probe) 250.00 cop[tikv] group by:planner__core__casetest__physicalplantest__physical_plan.tb.id, funcs:sum(planner__core__casetest__physicalplantest__physical_plan.tb.code)->Column#15
3208+
└─TableRowIDScan 250.00 cop[tikv] table:tb keep order:false, stats:pseudo
32083209
SELECT ta.NAME,(SELECT sum(tb.CODE) FROM tb WHERE ta.id = tb.id) tb_sum_code FROM ta WHERE ta.NAME LIKE 'chad999%';
32093210
NAME tb_sum_code
32103211
show warnings;
@@ -3325,11 +3326,11 @@ Projection 9.99 root planner__core__casetest__physicalplantest__physical_plan.t
33253326
│ └─Selection(Probe) 9.99 cop[tikv] not(isnull(planner__core__casetest__physicalplantest__physical_plan.ta.id))
33263327
│ └─TableRowIDScan 10.00 cop[tikv] table:ta keep order:false, stats:pseudo
33273328
└─Selection(Probe) 63872.06 root gt(Column#9, 900)
3328-
└─HashAgg 79840.08 root group by:planner__core__casetest__physicalplantest__physical_plan.tb.id, funcs:max(Column#13)->Column#9, funcs:firstrow(planner__core__casetest__physicalplantest__physical_plan.tb.id)->planner__core__casetest__physicalplantest__physical_plan.tb.id
3329-
└─IndexLookUp 79840.08 root
3329+
└─HashAgg 9.99 root group by:planner__core__casetest__physicalplantest__physical_plan.tb.id, funcs:max(Column#13)->Column#9, funcs:firstrow(planner__core__casetest__physicalplantest__physical_plan.tb.id)->planner__core__casetest__physicalplantest__physical_plan.tb.id
3330+
└─IndexLookUp 9.99 root
33303331
├─Selection(Build) 9.99 cop[tikv] not(isnull(planner__core__casetest__physicalplantest__physical_plan.tb.id))
33313332
│ └─IndexRangeScan 10.00 cop[tikv] table:tb, index:idx_tb_id(id) range: decided by [eq(planner__core__casetest__physicalplantest__physical_plan.tb.id, planner__core__casetest__physicalplantest__physical_plan.ta.id)], keep order:false, stats:pseudo
3332-
└─HashAgg(Probe) 79840.08 cop[tikv] group by:planner__core__casetest__physicalplantest__physical_plan.tb.id, funcs:max(planner__core__casetest__physicalplantest__physical_plan.tb.code)->Column#13
3333+
└─HashAgg(Probe) 9.99 cop[tikv] group by:planner__core__casetest__physicalplantest__physical_plan.tb.id, funcs:max(planner__core__casetest__physicalplantest__physical_plan.tb.code)->Column#13
33333334
└─TableRowIDScan 9.99 cop[tikv] table:tb keep order:false, stats:pseudo
33343335
SELECT ta.id, 'split' as flag FROM ta WHERE ta.NAME ='chad999' and (select max(tb.code) from tb where ta.id=tb.id ) > 900;
33353336
id flag

tests/integrationtest/r/planner/core/indexjoin.result

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ Projection 9990.00 root planner__core__indexjoin.t.a, Column#4, planner__core__
5252
└─IndexJoin 9990.00 root inner join, inner:HashAgg, outer key:planner__core__indexjoin.t1.a, inner key:planner__core__indexjoin.t.a, equal cond:eq(planner__core__indexjoin.t1.a, planner__core__indexjoin.t.a)
5353
├─IndexReader(Build) 9990.00 root index:IndexFullScan
5454
│ └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx(a, b) keep order:false, stats:pseudo
55-
└─HashAgg(Probe) 79840080.00 root group by:planner__core__indexjoin.t.a, funcs:count(Column#8)->Column#4, funcs:firstrow(planner__core__indexjoin.t.a)->planner__core__indexjoin.t.a
56-
└─IndexReader 79840080.00 root index:HashAgg
57-
└─HashAgg 79840080.00 cop[tikv] group by:planner__core__indexjoin.t.a, funcs:count(planner__core__indexjoin.t.b)->Column#8
55+
└─HashAgg(Probe) 9990.00 root group by:planner__core__indexjoin.t.a, funcs:count(Column#8)->Column#4, funcs:firstrow(planner__core__indexjoin.t.a)->planner__core__indexjoin.t.a
56+
└─IndexReader 9990.00 root index:HashAgg
57+
└─HashAgg 9990.00 cop[tikv] group by:planner__core__indexjoin.t.a, funcs:count(planner__core__indexjoin.t.b)->Column#8
5858
└─Selection 9990.00 cop[tikv] not(isnull(planner__core__indexjoin.t.a))
5959
└─IndexRangeScan 10000.00 cop[tikv] table:t, index:idx(a, b) range: decided by [eq(planner__core__indexjoin.t.a, planner__core__indexjoin.t1.a)], keep order:false, stats:pseudo
6060
select /*+ INL_JOIN(tmp) */ t1.a, tmp.count_b from (select a, count(b) count_b from t group by a) tmp, t1 where tmp.a=t1.a order by t1.a, tmp.count_b;
@@ -73,9 +73,9 @@ Projection 9980.01 root planner__core__indexjoin.t.a, Column#4, planner__core__
7373
├─IndexReader(Build) 9980.01 root index:Selection
7474
│ └─Selection 9980.01 cop[tikv] not(isnull(planner__core__indexjoin.t1.b))
7575
│ └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx(a, b) keep order:false, stats:pseudo
76-
└─HashAgg(Probe) 79760239.92 root group by:planner__core__indexjoin.t.a, funcs:count(Column#8)->Column#4, funcs:firstrow(planner__core__indexjoin.t.a)->planner__core__indexjoin.t.a
77-
└─IndexReader 79760239.92 root index:HashAgg
78-
└─HashAgg 79760239.92 cop[tikv] group by:planner__core__indexjoin.t.a, funcs:count(planner__core__indexjoin.t.b)->Column#8
76+
└─HashAgg(Probe) 9980.01 root group by:planner__core__indexjoin.t.a, funcs:count(Column#8)->Column#4, funcs:firstrow(planner__core__indexjoin.t.a)->planner__core__indexjoin.t.a
77+
└─IndexReader 9980.01 root index:HashAgg
78+
└─HashAgg 9980.01 cop[tikv] group by:planner__core__indexjoin.t.a, funcs:count(planner__core__indexjoin.t.b)->Column#8
7979
└─Selection 9980.01 cop[tikv] not(isnull(planner__core__indexjoin.t.a))
8080
└─IndexRangeScan 9990.00 cop[tikv] table:t, index:idx(a, b) range: decided by [eq(planner__core__indexjoin.t.a, planner__core__indexjoin.t1.a)], keep order:false, stats:pseudo
8181
select /*+ INL_JOIN(tmp) */ t1.a, tmp.count_b from (select a, count(b) count_b from t group by a) tmp, t1 where tmp.a=t1.a and tmp.count_b = t1.b order by t1.a, tmp.count_b;
@@ -170,9 +170,9 @@ Projection 9990.00 root planner__core__indexjoin.t3.b, planner__core__indexjoin
170170
├─TableReader(Build) 9990.00 root data:Selection
171171
│ └─Selection 9990.00 cop[tikv] not(isnull(planner__core__indexjoin.t4.b))
172172
│ └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo
173-
└─HashAgg(Probe) 79840080.00 root group by:planner__core__indexjoin.t3.b, funcs:firstrow(planner__core__indexjoin.t3.b)->planner__core__indexjoin.t3.b
174-
└─IndexReader 79840080.00 root index:HashAgg
175-
└─HashAgg 79840080.00 cop[tikv] group by:planner__core__indexjoin.t3.b,
173+
└─HashAgg(Probe) 9990.00 root group by:planner__core__indexjoin.t3.b, funcs:firstrow(planner__core__indexjoin.t3.b)->planner__core__indexjoin.t3.b
174+
└─IndexReader 9990.00 root index:HashAgg
175+
└─HashAgg 9990.00 cop[tikv] group by:planner__core__indexjoin.t3.b,
176176
└─Selection 9990.00 cop[tikv] not(isnull(planner__core__indexjoin.t3.b))
177177
└─IndexRangeScan 10000.00 cop[tikv] table:t3, index:idx(b) range: decided by [eq(planner__core__indexjoin.t3.b, planner__core__indexjoin.t4.b)], keep order:false, stats:pseudo
178178
select /*+ INL_JOIN(tmp) */ tmp.b, t4.b from (select b from t3 group by b) tmp, t4 where tmp.b=t4.b order by tmp.b, t4.b;
@@ -205,9 +205,9 @@ Projection 9990.00 root planner__core__indexjoin.t.a, Column#4, planner__core__
205205
└─IndexJoin 9990.00 root inner join, inner:StreamAgg, outer key:planner__core__indexjoin.t1.a, inner key:planner__core__indexjoin.t.a, equal cond:eq(planner__core__indexjoin.t1.a, planner__core__indexjoin.t.a)
206206
├─IndexReader(Build) 9990.00 root index:IndexFullScan
207207
│ └─IndexFullScan 9990.00 cop[tikv] table:t1, index:idx(a, b) keep order:false, stats:pseudo
208-
└─StreamAgg(Probe) 79840080.00 root group by:planner__core__indexjoin.t.a, funcs:count(Column#8)->Column#4, funcs:firstrow(planner__core__indexjoin.t.a)->planner__core__indexjoin.t.a
209-
└─IndexReader 79840080.00 root index:StreamAgg
210-
└─StreamAgg 79840080.00 cop[tikv] group by:planner__core__indexjoin.t.a, funcs:count(planner__core__indexjoin.t.b)->Column#8
208+
└─StreamAgg(Probe) 9990.00 root group by:planner__core__indexjoin.t.a, funcs:count(Column#8)->Column#4, funcs:firstrow(planner__core__indexjoin.t.a)->planner__core__indexjoin.t.a
209+
└─IndexReader 9990.00 root index:StreamAgg
210+
└─StreamAgg 9990.00 cop[tikv] group by:planner__core__indexjoin.t.a, funcs:count(planner__core__indexjoin.t.b)->Column#8
211211
└─Selection 9990.00 cop[tikv] not(isnull(planner__core__indexjoin.t.a))
212212
└─IndexRangeScan 10000.00 cop[tikv] table:t, index:idx(a, b) range: decided by [eq(planner__core__indexjoin.t.a, planner__core__indexjoin.t1.a)], keep order:true, stats:pseudo
213213
explain format='brief' select /*+ INL_JOIN(tmp) */ * from (select /*+ stream_agg() */ b, a from t group by b, a) tmp, t1 where tmp.a=t1.a;

0 commit comments

Comments
 (0)