Bug #118009 SELECT query on primary key column deteriorates to full table scan when filter involves too long string
Submitted: 18 Apr 7:13 Modified: 18 Apr 11:31
Reporter: Pawel Kudzia Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S5 (Performance)
Version:8.4.5, 9.3.0 OS:Debian (12)
Assigned to: CPU Architecture:x86 (amd64)
Tags: regression

[18 Apr 7:13] Pawel Kudzia
Description:
SELECT query, that should use primary index, deteriorates to a full table scan when filtering part of WHERE refers in IN to 2 or more values, where at at least one of them is longer than defined length of the column.

How to repeat:
MySQL 8.4.5 with default settings, installed from Oracle's MySQL APT repository.

CREATE TABLE t ( c varchar(16) NOT NULL , PRIMARY KEY (c) );

some test data:

INSERT INTO t(c) VALUES('a'),('b'),('c'),('d'),('e'),('f'),('g'),('h'),('i'),('j'),('k'),('l'),('m'),('n'),('o'),('p'),('q'),('r'),('s'),('t'),('u');

INSERT IGNORE INTO t(c) SELECT SUBSTR(MD5(CONCAT(t1.c, ROW_NUMBER() OVER ( PARTITION BY 'x')) ),1,16) FROM t t1 JOIN t t2 ORDER BY t1.c;
INSERT IGNORE INTO t(c) SELECT SUBSTR(MD5(CONCAT(t1.c, ROW_NUMBER() OVER ( PARTITION BY 'x')) ),1,16) FROM t t1 JOIN t t2 ORDER BY t1.c;

this query works as expected, there's no full table scan:

mysql> EXPLAIN SELECT * FROM t WHERE c IN ( '012345678901234567');
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                          |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
|  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | no matching row in const table |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+

but adding one more value into the IN list, even short one - leads to full table scan:

mysql> explain SELECT * FROM t WHERE c IN ( '012345678901234567','a' );
+----+-------------+-------+------------+-------+---------------+---------+---------+------+--------+----------+--------------------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows   | filtered | Extra                    |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+--------+----------+--------------------------+
|  1 | SIMPLE      | t     | NULL       | index | PRIMARY       | PRIMARY | 66      | NULL | 223855 |    20.00 | Using where; Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+--------+----------+--------------------------+

Suggested fix:
in the ideal world - query planner should make use of the index even if some of the values in IN list have length longer than maximum allowed column length; for them there'll be no matching row.

thank you!
[18 Apr 11:31] MySQL Verification Team
Hello Pawel Kudzia,

Thank you for the report and test case.
Verified as described.

regards,
Umesh