Bug #84818 index_merge_intersection not returning proper results
Submitted: 4 Feb 2017 23:07 Modified: 6 Feb 2017 17:54
Reporter: Steve Bink Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S3 (Non-critical)
Version:5.7.17 OS:Ubuntu (Linux homedev 4.4.0-59-generic #80-Ubuntu SMP Fri Jan 6 17:47:47 UTC 2017 x86_64 x86_64 x86_64 GNU/L)
Assigned to: CPU Architecture:Any

[4 Feb 2017 23:07] Steve Bink
Description:
Rows are missing from the results when using a correlated subquery with count(*).

Possibly related to:
https://bugs.mysql.com/bug.php?id=69581
https://bugs.mysql.com/bug.php?id=70703
https://bugs.mysql.com/bug.php?id=81031

How to repeat:
#> mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.17-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select @@optimizer_switch;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| @@optimizer_switch                                                                                                                                                                                                                                                                                                                                                                                               |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> create database bugtest;
Query OK, 1 row affected (0.00 sec)

mysql> use bugtest;
Database changed
mysql> DROP TABLE IF EXISTS T2;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> CREATE TABLE `T1` (
    ->   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    ->   PRIMARY KEY (`id`)
    -> ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query OK, 0 rows affected (0.04 sec)

mysql> INSERT INTO `T1` (`id`) VALUES
    -> (1),
    -> (2);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> CREATE TABLE `T2` (
    ->   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    ->   `t1_id` int(10) unsigned DEFAULT NULL,
    ->   `locale` varchar(3) COLLATE utf8_unicode_ci DEFAULT NULL,
    ->   `title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
    ->   PRIMARY KEY (`id`),
    ->   KEY `ndx_t2_t1_id` (`t1_id`),
    ->   KEY `ndx_t2_locale` (`locale`)
    -> ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query OK, 0 rows affected (0.06 sec)

mysql> INSERT INTO `T2` (`id`, `t1_id`, `locale`, `title`) VALUES
    -> (1, 1, 'en', 'e1'),
    -> (2, 1, 'fr', 'f1'),
    -> (3, 2, 'en', 'e2'),
    -> (4, 2, 'fr', 'f2');
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from `T1`
    -> where
    -> (select count(*)
    ->   from `T2` where `T2`.`t1_id` = `T1`.`id` and `locale` = 'en') >= 1
    -> and `T1`.`id` = 2;
Empty set (0.01 sec)

mysql> explain select * from `T1`  where  (select count(*)    from `T2` where `T2`.`t1_id` = `T1`.`id` and `locale` = 'en') >= 1  and `T1`.`id` = 2;
+----+--------------------+-------+------------+-------------+----------------------------+----------------------------+---------+-------+------+----------+-----------------------------------------------------------------------+
| id | select_type        | table | partitions | type        | possible_keys              | key                        | key_len | ref   | rows | filtered | Extra                                                                 |
+----+--------------------+-------+------------+-------------+----------------------------+----------------------------+---------+-------+------+----------+-----------------------------------------------------------------------+
|  1 | PRIMARY            | T1    | NULL       | const       | PRIMARY                    | PRIMARY                    | 4       | const |    1 |   100.00 | Using index                                                           |
|  2 | DEPENDENT SUBQUERY | T2    | NULL       | index_merge | ndx_t2_t1_id,ndx_t2_locale | ndx_t2_t1_id,ndx_t2_locale | 5,12    | NULL  |    1 |   100.00 | Using intersect(ndx_t2_t1_id,ndx_t2_locale); Using where; Using index |
+----+--------------------+-------+------------+-------------+----------------------------+----------------------------+---------+-------+------+----------+-----------------------------------------------------------------------+
2 rows in set, 2 warnings (0.00 sec)

mysql> show warnings;
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                                                                                               |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1276 | Field or reference 'bugtest.T1.id' of SELECT #2 was resolved in SELECT #1                                                                                                                             |
| Note  | 1003 | /* select#1 */ select '2' AS `id` from `bugtest`.`t1` where (((/* select#2 */ select count(0) from `bugtest`.`t2` where ((`bugtest`.`t2`.`t1_id` = '2') and (`bugtest`.`t2`.`locale` = 'en'))) >= 1)) |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> set session optimizer_switch='index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from `T1`  where  (select count(*)    from `T2` where `T2`.`t1_id` = `T1`.`id` and `locale` = 'en') >= 1  and `T1`.`id` = 2;                                                  +----+
| id |
+----+
|  2 |
+----+
1 row in set (0.00 sec)

mysql> explain select * from `T1`  where  (select count(*)    from `T2` where `T2`.`t1_id` = `T1`.`id` and `locale` = 'en') >= 1  and `T1`.`id` = 2;                                          +----+--------------------+-------+------------+-------+----------------------------+--------------+---------+-------+------+----------+-------------+
| id | select_type        | table | partitions | type  | possible_keys              | key          | key_len | ref   | rows | filtered | Extra       |
+----+--------------------+-------+------------+-------+----------------------------+--------------+---------+-------+------+----------+-------------+
|  1 | PRIMARY            | T1    | NULL       | const | PRIMARY                    | PRIMARY      | 4       | const |    1 |   100.00 | Using index |
|  2 | DEPENDENT SUBQUERY | T2    | NULL       | ref   | ndx_t2_t1_id,ndx_t2_locale | ndx_t2_t1_id | 5       | const |    2 |    50.00 | Using where |
+----+--------------------+-------+------------+-------+----------------------------+--------------+---------+-------+------+----------+-------------+
2 rows in set, 2 warnings (0.00 sec)

mysql> show warnings;                                                                                                                                                                         +-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                                                                                               |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1276 | Field or reference 'bugtest.T1.id' of SELECT #2 was resolved in SELECT #1                                                                                                                             |
| Note  | 1003 | /* select#1 */ select '2' AS `id` from `bugtest`.`t1` where (((/* select#2 */ select count(0) from `bugtest`.`t2` where ((`bugtest`.`t2`.`t1_id` = '2') and (`bugtest`.`t2`.`locale` = 'en'))) >= 1)) |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
[5 Feb 2017 2:45] Gauthier Van Vreckem
probably a duplicate of 
https://bugs.mysql.com/bug.php?id=79675
[6 Feb 2017 17:54] MySQL Verification Team
Hi,

Thank you for your bug report. I have tested it and indeed, it is a duplicate of the bug:

https://bugs.mysql.com/bug.php?id=79675

Follow the destiny of the above bug regarding its fixing.