Bug #101459 With more than one value in IN() clause, query skip index use.
Submitted: 4 Nov 2020 13:05 Modified: 12 Feb 2022 13:21
Reporter: lalit Choudhary Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S5 (Performance)
Version:5.6.50,5.7.32 OS:Any
Assigned to: CPU Architecture:Any
Tags: regression

[4 Nov 2020 13:05] lalit Choudhary
Description:
Select Queries like in below example with more than one value in IN() clause, skip index use.

Issue Reproduciable with 5.6.50 and 5.7.32, Same issue not reproduciable with 8.0.21

mysql > explain select updated_at from t1 where status in ('abc', 'xyz') and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: ALL
possible_keys: inx_key1,inx_key2
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
        Extra: Using where
1 row in set (0.01 sec)

How to repeat:
Issue Reproduciable with 5.6.50 and 5.7.32, Same issue not reproduciable with 8.0.21

Test case:
CREATE TABLE `t1` (`id` int(11) NOT NULL AUTO_INCREMENT,
`status` varchar(10) DEFAULT 'new' ,
`priority` int(11) DEFAULT '300',
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `inx_key1` (`status`,`priority`),
KEY `inx_key2` (`status`,`updated_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

MySQL 5.6.50

mysql [localhost] {msandbox} (test) > explain select updated_at from t1 where status in ('abc', 'xyz') and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: ALL
possible_keys: inx_key1,inx_key2
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
        Extra: Using where
1 row in set (0.01 sec)

mysql [localhost] {msandbox} (test) > explain select updated_at from t1 where status in ('abc') and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: ref
possible_keys: inx_key1,inx_key2
          key: inx_key2
      key_len: 33
          ref: const
         rows: 1
        Extra: Using index condition; Using where
1 row in set (0.00 sec)

MySQL 5.7.32

mysql [localhost] {msandbox} (test) > explain select updated_at from t1 where status in ('abc', 'xyz') and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: inx_key1,inx_key2
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.01 sec)

mysql [localhost] {msandbox} (test) > explain select updated_at from t1 where status in ('abc') and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ref
possible_keys: inx_key1,inx_key2
          key: inx_key2
      key_len: 33
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

1 row in set (0.00 sec)

********************
MySQL-8.0.21  works fine:

mysql [localhost] {msandbox} (test) > explain select updated_at from t1 where status in ('abc', 'xyz') and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: range
possible_keys: inx_key1,inx_key2
          key: inx_key2
      key_len: 33
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: Using index condition; Using where
1 row in set, 1 warning (0.00 sec)

mysql [localhost] {msandbox} (test) > explain select updated_at from t1 where status in ('abc') and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ref
possible_keys: inx_key1,inx_key2
          key: inx_key2
      key_len: 33
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

mysql [localhost] {msandbox} (test) > exit
Bye

Suggested fix:
It should use index regardless of the number of values specified in IN() clause.
[5 Nov 2020 11:56] MySQL Verification Team
Hello Lalit,

Thank you for the report and feedback!

Thanks,
Umesh
[12 Feb 2022 13:21] lalit Choudhary
same issue with AND clause as well,

mysql [localhost] {msandbox} (test) > explain select updated_at from t1 where status='abc' and status='xyz' and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: NULL
   partitions: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
     filtered: NULL
        Extra: Impossible WHERE
1 row in set, 1 warning (0.00 sec)

mysql [localhost] {msandbox} (test) > explain select updated_at from t1 where status='abc'  and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ref
possible_keys: inx_key1,inx_key2
          key: inx_key2
      key_len: 33
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

mysql [localhost] {msandbox} (test) >
[28 Feb 2022 15:34] Truls Bergskaug
Same for MySQL 5.7.37:

mysql> show global variables like '%version%';
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| innodb_version          | 5.7.37                       |
| protocol_version        | 10                           |
| slave_type_conversions  |                              |
| tls_version             | TLSv1,TLSv1.1,TLSv1.2        |
| version                 | 5.7.37-log                   |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | Linux                        |
+-------------------------+------------------------------+
8 rows in set (0.00 sec)

mysql> explain select updated_at from t1 where status in ('abc', 'xyz') and priority != 100 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: inx_key1,inx_key2
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 5
     filtered: 80.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)