pingcap / pingcap/tidb

Join order hints don't work due to left condition on left join conditions

Open
#51,384 4 comments 0 reactions 1 assignee Claimed by @qw4990 View on GitHub
epic/hint report/customer sig/planner type/enhancement
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

```
create table a(id int key);
create table b(id int key);
create table c(id int key);
create table d(id int key);
explain select /*+ leading(a,b,c,d) */ * from a, b left join c on b.id=c.id left join d on b.id=d.id and c.id is not null where a.id=b.id;
explain select /*+ straight_join() */ * from a, b left join c on b.id=c.id left join d on b.id=d.id and c.id is not null where a.id=b.id;
```

### 2. What did you expect to see? (Required)

```
mysql> explain select * from a straight_join b left join c on b.id=c.id left join d on b.id=d.id and c.id is not null where a.id=b.id;
+---------------------------------+----------+-----------+----------------------------+----------------------------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+---------------------------------+----------+-----------+----------------------------+----------------------------------------------------------------------------------------------------------------+
| HashJoin_20 | 19531.25 | root | | left outer join, equal:[eq(test.b.id, test.d.id) eq(test.a.id, test.d.id)], left cond:[not(isnull(test.c.id))] |
| ├─IndexReader_72(Build) | 10000.00 | root | | index:IndexFullScan_71 |
| │ └─IndexFullScan_71 | 10000.00 | cop[tikv] | table:d, index:PRIMARY(id) | keep order:false, stats:pseudo |
| └─HashJoin_30(Probe) | 15625.00 | root | | left outer join, equal:[eq(test.b.id, test.c.id) eq(test.a.id, test.c.id)] |
| ├─IndexReader_68(Build) | 10000.00 | root | | index:IndexFullScan_67 |
| │ └─IndexFullScan_67 | 10000.00 | cop[tikv] | table:c, index:PRIMARY(id) | keep order:false, stats:pseudo |
| └─MergeJoin_32(Probe) | 12500.00 | root | | inner join, left key:test.a.id, right key:test.b.id |
| ├─IndexReader_56(Build) | 10000.00 | root | | index:IndexFullScan_55 |
| │ └─IndexFullScan_55 | 10000.00 | cop[tikv] | table:b, index:PRIMARY(id) | keep order:true, stats:pseudo |
| └─IndexReader_54(Probe) | 10000.00 | root | | index:IndexFullScan_53 |
| └─IndexFullScan_53 | 10000.00 | cop[tikv] | table:a, index:PRIMARY(id) | keep order:true, stats:pseudo |
+---------------------------------+----------+-----------+----------------------------+----------------------------------------------------------------------------------------------------------------+
11 rows in set (0.00 sec)
```
### 3. What did you see instead (Required)

```
mysql> explain select /*+ leading(a,b,c,d) */ * from a, b left join c on b.id=c.id left join d on b.id=d.id and c.id is not null where a.id=b.id;
+-----------------------------------+----------+-----------+----------------------------+----------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+-----------------------------------+----------+-----------+----------------------------+----------------------------------------------------------------------------------------------+
| MergeJoin_13 | 19531.25 | root | | inner join, left key:test.a.id, right key:test.b.id |
| ├─MergeJoin_27(Build) | 15625.00 | root | | left outer join, left key:test.b.id, right key:test.d.id, left cond:[not(isnull(test.c.id))] |
| │ ├─IndexReader_52(Build) | 10000.00 | root | | index:IndexFullScan_51 |
| │ │ └─IndexFullScan_51 | 10000.00 | cop[tikv] | table:d, index:PRIMARY(id) | keep order:true, stats:pseudo |
| │ └─MergeJoin_37(Probe) | 12500.00 | root | | left outer join, left key:test.b.id, right key:test.c.id |
| │ ├─IndexReader_50(Build) | 10000.00 | root | | index:IndexFullScan_49 |
| │ │ └─IndexFullScan_49 | 10000.00 | cop[tikv] | table:c, index:PRIMARY(id) | keep order:true, stats:pseudo |
| │ └─IndexReader_48(Probe) | 10000.00 | root | | index:IndexFullScan_47 |
| │ └─IndexFullScan_47 | 10000.00 | cop[tikv] | table:b, index:PRIMARY(id) | keep order:true, stats:pseudo |
| └─IndexReader_26(Probe) | 10000.00 | root | | index:IndexFullScan_25 |
| └─IndexFullScan_25 | 10000.00 | cop[tikv] | table:a, index:PRIMARY(id) | keep order:true, stats:pseudo |
+-----------------------------------+----------+-----------+----------------------------+----------------------------------------------------------------------------------------------+
11 rows in set, 2 warnings (0.00 sec)

mysql> show warnings;
+---------+------+------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------------------------------------+
| Warning | 1815 | leading hint is inapplicable, check if the leading hint table is valid |
| Warning | 1815 | leading hint is inapplicable, check if the leading hint table is valid |
+---------+------+------------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> explain select /*+ straight_join() */ * from a, b left join c on b.id=c.id left join d on b.id=d.id and c.id is not null where a.id=b.id;
+-----------------------------------+----------+-----------+----------------------------+----------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+-----------------------------------+----------+-----------+----------------------------+----------------------------------------------------------------------------------------------+
| MergeJoin_11 | 19531.25 | root | | inner join, left key:test.a.id, right key:test.b.id |
| ├─MergeJoin_25(Build) | 15625.00 | root | | left outer join, left key:test.b.id, right key:test.d.id, left cond:[not(isnull(test.c.id))] |
| │ ├─IndexReader_50(Build) | 10000.00 | root | | index:IndexFullScan_49 |
| │ │ └─IndexFullScan_49 | 10000.00 | cop[tikv] | table:d, index:PRIMARY(id) | keep order:true, stats:pseudo |
| │ └─MergeJoin_35(Probe) | 12500.00 | root | | left outer join, left key:test.b.id, right key:test.c.id |
| │ ├─IndexReader_48(Build) | 10000.00 | root | | index:IndexFullScan_47 |
| │ │ └─IndexFullScan_47 | 10000.00 | cop[tikv] | table:c, index:PRIMARY(id) | keep order:true, stats:pseudo |
| │ └─IndexReader_46(Probe) | 10000.00 | root | | index:IndexFullScan_45 |
| │ └─IndexFullScan_45 | 10000.00 | cop[tikv] | table:b, index:PRIMARY(id) | keep order:true, stats:pseudo |
| └─IndexReader_24(Probe) | 10000.00 | root | | index:IndexFullScan_23 |
| └─IndexFullScan_23 | 10000.00 | cop[tikv] | table:a, index:PRIMARY(id) | keep order:true, stats:pseudo |
+-----------------------------------+----------+-----------+----------------------------+----------------------------------------------------------------------------------------------+
11 rows in set (0.00 sec)
```

### 4. What is your TiDB version? (Required)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.