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: | |
| Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
| Version: | 5.6.50,5.7.32 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | regression | ||
[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)
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.055 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
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.