pingcap/tidb

query optimizer does not detect "provable empty sets"

Open

#25,539 opened on Jun 17, 2021

View on GitHub
 (2 comments) (0 reactions) (1 assignee)Go (40,090 stars) (6,186 forks)batch import
help wantedsig/plannertype/enhancement

Description

Bug Report

This is issue (7) on https://blog.jooq.org/2017/09/28/10-cool-sql-optimisations-that-do-not-depend-on-the-cost-model/

1. Minimal reproduce step (Required)

DROP TABLE IF EXISTS t1, t2;

CREATE TABLE t1 (
 id INT NOT NULL PRIMARY KEY auto_increment,
 t2_id INT NOT NULL,
 pad1 varchar(100)
);

CREATE TABLE t2 (
 id INT NOT NULL PRIMARY KEY auto_increment,
 nn_col INT NOT NULL,
 pad1 varchar(100)
);
 
INSERT INTO t2 SELECT NULL, 1, 'aaa' FROM dual;
INSERT INTO t2 SELECT NULL, 1, 'aaa' FROM t2 a JOIN t2 b JOIN t2 c;
INSERT INTO t1 SELECT NULL, id, 'aaa' FROM t2;

EXPLAIN SELECT t1.* FROM t1 JOIN (SELECT * FROM t2 WHERE nn_col IS NULL) t2 WHERE t1.t2_id = t2.id;

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

Here is what MySQL says:

mysql [localhost:8024] {root} (test) > EXPLAIN SELECT t1.* FROM t1 JOIN (SELECT * FROM t2 WHERE nn_col IS NULL) t2 WHERE t1.t2_id = t2.id;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra            |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
|  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Impossible WHERE |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
1 row in set, 1 warning (0.00 sec)

3. What did you see instead (Required)

mysql> EXPLAIN SELECT t1.* FROM t1 JOIN (SELECT * FROM t2 WHERE nn_col IS NULL) t2 WHERE t1.t2_id = t2.id;
+-----------------------------+----------+-----------+---------------+---------------------------------------------------+
| id                          | estRows  | task      | access object | operator info                                     |
+-----------------------------+----------+-----------+---------------+---------------------------------------------------+
| HashJoin_14                 | 0.00     | root      |               | inner join, equal:[eq(test.t2.id, test.t1.t2_id)] |
| ├─TableDual_18(Build)       | 0.00     | root      |               | rows:0                                            |
| └─TableReader_17(Probe)     | 10000.00 | root      |               | data:TableFullScan_16                             |
|   └─TableFullScan_16        | 10000.00 | cop[tikv] | table:t1      | keep order:false, stats:pseudo                    |
+-----------------------------+----------+-----------+---------------+---------------------------------------------------+
4 rows in set (0.00 sec)

4. What is your TiDB version? (Required)

mysql> SELECT tidb_version()\G
*************************** 1. row ***************************
tidb_version(): Release Version: v5.2.0-alpha-81-g62b70d310-dirty
Edition: Community
Git Commit Hash: 62b70d3101c6dbb06f1f7f4005eba28344932ee4
Git Branch: alter-user-for-self
UTC Build Time: 2021-06-16 14:44:37
GoVersion: go1.16.4
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false
1 row in set (0.00 sec)

Contributor guide