[MDEV-11859] Execution plans of the the first and the second executions of a prepared statement are not the same. Created: 2017-01-21  Updated: 2017-01-24  Resolved: 2017-01-24

Status: Closed
Project: MariaDB Server
Component/s: Optimizer
Affects Version/s: 5.5, 10.0, 10.1, 10.2
Fix Version/s: 5.5.55

Type: Bug Priority: Major
Reporter: Igor Babaev Assignee: Igor Babaev
Resolution: Fixed Votes: 0
Labels: None


 Description   

If the where condition of a query contains a non-correlated, non-expensive subquery then
then different executions of the prepared statement made for the query may use
different execution plans.

The following test case demonstrates this.

 create table t1 (id int, c varchar(3), key idx(c))engine=myisam;
insert into t1 values (3,'bar'), (1,'xxx'), (2,'foo'), (5,'yyy');
 
prepare stmt1 from
"explain extended
 select * from t1 where (1, 2) in ( select 3, 4 ) or c = 'foo'";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
 
prepare stmt2 from
"explain extended
 select * from t1 where (1, 2) in ( select 3, 4 )";
execute stmt2;
execute stmt2;
deallocate prepare stmt2;
 
drop table t1;

Here for the first and the second executions of the prepared statement stmt1 we have:

MariaDB [test]> execute stmt1;
+------+-------------+-------+------+---------------+------+---------+-------+------+----------+-----------------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra                 |
+------+-------------+-------+------+---------------+------+---------+-------+------+----------+-----------------------+
|    1 | PRIMARY     | t1    | ref  | idx           | idx  | 6       | const |    1 |   100.00 | Using index condition |
|    2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL  | NULL |     NULL | No tables used        |
+------+-------------+-------+------+---------------+------+---------+-------+------+----------+-----------------------+
 
MariaDB [test]> execute stmt1;
+------+-------------+-------+------+---------------+------+---------+------+------+----------+----------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra          |
+------+-------------+-------+------+---------------+------+---------+------+------+----------+----------------+
|    1 | PRIMARY     | t1    | ALL  | idx           | NULL | NULL    | NULL |    4 |   100.00 | Using where    |
|    2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | No tables used |
+------+-------------+-------+------+---------------+------+---------+------+------+----------+----------------+

While for the first and the second executions of the prepared statement stmt2 the plans are
as follows:

ariaDB [test]> execute stmt2;
+------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra            |
+------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+
|    1 | PRIMARY     | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Impossible WHERE |
|    2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | No tables used   |
+------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+
 
MariaDB [test]> execute stmt2;
+------+-------------+-------+------+---------------+------+---------+------+------+----------+----------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra          |
+------+-------------+-------+------+---------------+------+---------+------+------+----------+----------------+
|    1 | PRIMARY     | t1    | ALL  | NULL          | NULL | NULL    | NULL |    4 |   100.00 |                |
|    2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | No tables used |
+------+-------------+-------+------+---------------+------+---------+------+------+----------+----------------+



 Comments   
Comment by Igor Babaev [ 2017-01-24 ]

This is a legacy bug.
I reproduced it in MariaDB-5.2. Most probably it can be reproduced in earlier versions of the mysql server.
The problem was that at the first execution of a prepared statement inexpensive uncorrelated subqueries from the WHERE clause were evaluated in the procedure optimize_cond(). The results of their evaluations could be used to simplify the WHERE condition.
At the second execution these subqueries wew not evaluated in optimize_cond().
It happened due to a bug in the code of Item_subselect::update_used_tables(). The code incorrectly determined whether an Item_subselect was constant item or not.

Comment by Igor Babaev [ 2017-01-24 ]

The fix for this bug was pushed into the 5.5 tree.
Should be merged upstream as it is.

Generated at Thu Feb 08 07:53:12 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.