Skip to content

Commit 424bb34

Browse files
authored
planner: don't choose merge join unless there's hint or join key fully matched (pingcap#59936) (pingcap#59946)
close pingcap#20710
1 parent d078286 commit 424bb34

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

pkg/planner/core/exhaust_physical_plans.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ func (p *LogicalJoin) GetMergeJoin(prop *property.PhysicalProperty, schema *expr
183183
offsets := getMaxSortPrefix(lhsChildProperty, leftJoinKeys)
184184
// If not all equal conditions hit properties. We ban merge join heuristically. Because in this case, merge join
185185
// may get a very low performance. In executor, executes join results before other conditions filter it.
186-
if len(offsets) < len(leftJoinKeys) {
186+
// And skip the cartesian join case, unless we force to use merge join.
187+
if len(offsets) < len(leftJoinKeys) || len(leftJoinKeys) == 0 {
187188
continue
188189
}
189190

@@ -195,7 +196,8 @@ func (p *LogicalJoin) GetMergeJoin(prop *property.PhysicalProperty, schema *expr
195196
}
196197

197198
prefixLen := findMaxPrefixLen(p.rightProperties, rightKeys)
198-
if prefixLen == 0 {
199+
// right side should also be full match.
200+
if prefixLen < len(offsets) || prefixLen == 0 {
199201
continue
200202
}
201203

tests/integrationtest/r/planner/core/issuetest/planner_issue.result

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,3 +619,26 @@ NULL NULL 2 2 4 2
619619
show warnings;
620620
Level Code Message
621621
drop table if exists t1, t2, t3, t4;
622+
drop table if exists t1, t2;
623+
create table t1(a int, b int, index idx(a, b));
624+
create table t2(a int, b int, index idx(a));
625+
explain select /*+ merge_join(t1) */ * from t1 join t2 on t1.a=t2.a and t2.b=t1.b;
626+
id estRows task access object operator info
627+
MergeJoin_8 12475.01 root inner join, left key:test.t1.a, test.t1.b, right key:test.t2.a, test.t2.b
628+
├─Sort_19(Build) 9980.01 root test.t2.a, test.t2.b
629+
│ └─TableReader_14 9980.01 root data:Selection_13
630+
│ └─Selection_13 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))
631+
│ └─TableFullScan_12 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo
632+
└─IndexReader_11(Probe) 9980.01 root index:Selection_10
633+
└─Selection_10 9980.01 cop[tikv] not(isnull(test.t1.b))
634+
└─IndexFullScan_9 9990.00 cop[tikv] table:t1, index:idx(a, b) keep order:true, stats:pseudo
635+
explain select /*+ no_hash_join(t1), no_index_join(t1,t2), no_index_hash_join(t1,t2) */ * from t1 join t2 on t1.a=t2.a and t2.b=t1.b;
636+
id estRows task access object operator info
637+
MergeJoin_8 12475.01 root inner join, left key:test.t1.a, test.t1.b, right key:test.t2.a, test.t2.b
638+
├─Sort_47(Build) 9980.01 root test.t2.a, test.t2.b
639+
│ └─TableReader_42 9980.01 root data:Selection_41
640+
│ └─Selection_41 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))
641+
│ └─TableFullScan_40 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo
642+
└─IndexReader_39(Probe) 9980.01 root index:Selection_38
643+
└─Selection_38 9980.01 cop[tikv] not(isnull(test.t1.b))
644+
└─IndexFullScan_37 9990.00 cop[tikv] table:t1, index:idx(a, b) keep order:true, stats:pseudo

tests/integrationtest/t/planner/core/issuetest/planner_issue.test

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,3 +478,10 @@ SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
478478
ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b order by 1, 2, 3, 4, 5;
479479
show warnings;
480480
drop table if exists t1, t2, t3, t4;
481+
482+
# TestIssue20710
483+
drop table if exists t1, t2;
484+
create table t1(a int, b int, index idx(a, b));
485+
create table t2(a int, b int, index idx(a));
486+
explain select /*+ merge_join(t1) */ * from t1 join t2 on t1.a=t2.a and t2.b=t1.b;
487+
explain select /*+ no_hash_join(t1), no_index_join(t1,t2), no_index_hash_join(t1,t2) */ * from t1 join t2 on t1.a=t2.a and t2.b=t1.b;

0 commit comments

Comments
 (0)