Bug #108808 MySQL optimizer: the execution order of explain execution plan and explain analy
Submitted: 18 Oct 2022 7:25 Modified: 18 Oct 2022 12:41
Reporter: YINGYIFNEG YING Email Updates:
Status: Can't repeat Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S5 (Performance)
Version:8.0.27 OS:Red Hat (CentOS Linux release 7.9.2009 (Core))
Assigned to: CPU Architecture:x86

[18 Oct 2022 7:25] YINGYIFNEG YING
Description:
Description:
    When using join buffer (hash join), the explain execution plan is inconsistent with MySQL's execution order of SQL when using explain analyze

mysql> analyze table sbtest1;
+--------------+---------+----------+----------+
| Table        | Op      | Msg_type | Msg_text |
+--------------+---------+----------+----------+
| test.sbtest1 | analyze | status   | OK       |
+--------------+---------+----------+----------+
1 row in set (0.01 sec)

mysql> analyze table sbtest2;
+--------------+---------+----------+----------+
| Table        | Op      | Msg_type | Msg_text |
+--------------+---------+----------+----------+
| test.sbtest2 | analyze | status   | OK       |
+--------------+---------+----------+----------+
1 row in set (0.00 sec)

explain 1:

mysql> EXPLAIN SELECT * FROM sbtest1 JOIN sbtest2 ON (sbtest1.k = sbtest2.k);
+----+-------------+---------+------------+------+---------------+------+---------+------+--------+----------+--------------------------------------------+
| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra                                      |
+----+-------------+---------+------------+------+---------------+------+---------+------+--------+----------+--------------------------------------------+
|  1 | SIMPLE      | sbtest1 | NULL       | ALL  | NULL          | NULL | NULL    | NULL |  98712 |   100.00 | NULL                                       |
|  1 | SIMPLE      | sbtest2 | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 986400 |    10.00 | Using where; Using join buffer (hash join) |
+----+-------------+---------+------------+------+---------------+------+---------+------+--------+----------+--------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

explain 2:

mysql> EXPLAIN analyze SELECT * FROM sbtest1 JOIN sbtest2 ON (sbtest1.k = sbtest2.k);

+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN                                                                                                                                                            |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Inner hash join (sbtest2.k = sbtest1.k)  (cost=9736969017.40 rows=9736951825) (actual time=345.360..76310.340 rows=1000000000 loops=1)
    -> Table scan on sbtest2  (cost=0.17 rows=986400) (actual time=0.034..362.477 rows=1000000 loops=1)
    -> Hash
        -> Table scan on sbtest1  (cost=10215.95 rows=98712) (actual time=0.057..27.898 rows=100000 loops=1)
 |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (5 min 7.46 sec)

explain 1 It uses sbtest1 as the drive table
explain 2 It uses sbtest2 as the drive table,
so  The two execution plans are inconsistent 

How to repeat:
mysql> show create table sbtest1;
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table   | Create Table                                                                                |
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| sbtest1 | CREATE TABLE `sbtest1` (
  `id` int NOT NULL AUTO_INCREMENT,
  `k` int NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> show create table sbtest2;
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table   | Create Table                                                                                 |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| sbtest2 | CREATE TABLE `sbtest2` (
  `id` int NOT NULL AUTO_INCREMENT,
  `k` int NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

EXPLAIN SELECT * FROM sbtest1 JOIN sbtest2 ON (sbtest1.k = sbtest2.k);
EXPLAIN analyze SELECT * FROM sbtest1 JOIN sbtest2 ON (sbtest1.k = sbtest2.k);
[18 Oct 2022 12:41] MySQL Verification Team
Hello Mr. Ying,

Thank you for your bug report.

First of all, you are using an old release of MySQL 8.0. Current release is 8.0.31 and it has many improvements for the optimiser.

Second, we could not repeat your findings with our tables and our data ...... On that aspect, please read further on .....

Not enough information was provided for us to be able to handle this bug. Please re-read the instructions at http://bugs.mysql.com/how-to-report.php 

If you can provide more information, feel free to add it to this bug and if you provided a good test case, we shall  change the status back to 'Open'.  

Meanwhile, you have to be aware of another fact. If there is a difference between order of the tables in the  two EXPLAINs, it is "Not a Bug" !!! 

Simply, EXPLAIN alone does not go through all the stages of the optimisation, because it would then last as long as full query which returns data. On the other hand, EXPLAIN ANALYSE executes entire query, which enables it to calculate all costs and make better decisions on the proper order of the tables. Hence, it is a reason why order of the tables differ. Hence, your report is not a bug.

Thank you for your interest in MySQL.