Bug #106318 FORCE INDEX doesn't take effect when set jdbc param `useServerPrepStmts=true`

Submitted: 28 Jan 2022 2:01 Modified: 10 Feb 2022 6:21
Reporter: chen yi (OCA) Email Updates:
Status: Not a Bug Impact on me:
None 
Category:Connector / J Severity:S1 (Critical)
Version:8.0.25 OS:CentOS (CentOS Linux release 8.2.2004 (Core) )
Assigned to: CPU Architecture:x86 (Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS))

[28 Jan 2022 2:01] chen yi
Description:
FORCE INDEX doesn't take effect when set jdbc param `useServerPrepStmts=true`.
It takes very long time to fetch result. if we changed `useServerPrepStmts=true` to `false` or use `Statement` instead of `PreparedStatement` or replace `FORCE INDEX` to `FORCE INDEX FOR JOIN`. it's fast as normal.

How to repeat:
reproduce:
step 1: create table:

CREATE DATABASE PRICING;
USE PRICING:
CREATE TABLE `QUOTE` (
`ID` BIGINT NOT NULL,
`GROUP_ID` SMALLINT NOT NULL,
`SYMBOL_ID` SMALLINT NOT NULL,
`SOURCE_ID` BIGINT NULL DEFAULT NULL,
`PRODUCT_ID` INT NOT NULL,
`COMPANY_ID` TINYINT NOT NULL,
`LOW` DECIMAL(15,6) NOT NULL,
`HIGH` DECIMAL(15,6) NOT NULL,
`OPEN` DECIMAL(15,6) NOT NULL,
`SCALE` TINYINT NOT NULL,
`STATUS` TINYINT NOT NULL,
`LADDERED` TINYINT NOT NULL,
`DEVIATION` DECIMAL(15,6) NOT NULL,
`BID_PRICE` DECIMAL(15,6) NOT NULL,
`ASK_PRICE` DECIMAL(15,6) NOT NULL,
`QUOTE_DATE` DATE NOT NULL,
`QUOTE_TIME` BIGINT NOT NULL,
`BID_TRADABLE` TINYINT NOT NULL,
`ASK_TRADABLE` TINYINT NOT NULL,
`BID_ADJUSTMENT` DECIMAL(15,6) NOT NULL,
`ASK_ADJUSTMENT` DECIMAL(15,6) NOT NULL,
`VERSION` INT NOT NULL DEFAULT '1',
`INSERT_DATETIME` TIMESTAMP NULL DEFAULT NULL,
`UPDATE_DATETIME` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`ID`),
INDEX `INDEX_01` (`SOURCE_ID`),
INDEX `INDEX_02` (`PRODUCT_ID`),
INDEX `INDEX_03` (`PRODUCT_ID`, `QUOTE_DATE`),
INDEX `INDEX_04` (`PRODUCT_ID`, `QUOTE_TIME`)
)
ENGINE=InnoDB;

step 2: insert 10,000,000 records to above table. `PRODUCT_ID` 's cardinality is 200.

step 3: use following java code to access above table

public static void main(String[] args) throws SQLException {
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/PRICING?useServerPrepStmts=true", "user", "pass")) {
try (PreparedStatement ps = conn.prepareStatement("select * from QUOTE FORCE INDEX(INDEX_02) where PRODUCT_ID = ? order by ID desc limit 512")) {
ps.setInt(1, 10);
try (ResultSet rs = ps.executeQuery()) {
int count = 0;
while (rs.next()) {
count++;
}
System.out.println("count:" + count);
}
}
}
}

we expect above sql to use INDEX_02, key = INDEX_02, Extra = Backward index scan

mysql execution Plan:

mysql> EXPLAIN select * from QUOTE FORCE INDEX(INDEX_02) where PRODUCT_ID = 1 order by ID desc limit 512;
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+---------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+---------------------+
| 1 | SIMPLE | QUOTE | NULL | ref | INDEX_02 | INDEX_02 | 4 | const | 1 | 100.00 | Backward index scan |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+---------------------+
1 row in set, 1 warning (0.00 sec)
[28 Jan 2022 14:41] MySQL Verification Team
Hi,

What version of JDBC are you using?

Thanks
[29 Jan 2022 2:09] chen yi
Hi 
JDBC version same as MySql server version: 8.0.25
[31 Jan 2022 15:39] MySQL Verification Team
Hi,

This seems to be data specific. With data we can create it does not reproduce. 
I will verify this non the less for the connector team to take a look.

thanks
[9 Feb 2022 16:08] MySQL Verification Team
Hi,

This is not connector issue but change on server side as we are deprecating force index ...

https://dev.mysql.com/doc/refman/8.0/en/index-hints.html says:
 
The FORCE INDEX hint acts like USE INDEX (index_list), with the addition
that a table scan is assumed to be very expensive...

Note
As of MySQL 8.0.20, the server supports the index-level optimizer hints
JOIN_INDEX, GROUP_INDEX, ORDER_INDEX, and INDEX, which are equivalent to and
intended to supersede FORCE INDEX index hints, as well as the NO_JOIN_INDEX,
NO_GROUP_INDEX, NO_ORDER_INDEX, and NO_INDEX optimizer hints, which are
equivalent to and intended to supersede IGNORE INDEX index hints. Thus, you
should expect USE INDEX, FORCE INDEX, and IGNORE INDEX to be deprecated in a
future release of MySQL, and at some time thereafter to be removed
altogether. For more information, see Index-Level Optimizer Hints.
[10 Feb 2022 6:21] chen yi
Hi 
We already try index-level optimizer hints but same as bug described.
We perpared to install the newest Mysql version 8.0.28 and try reproduce again. I'll let you known if something found.
[10 Feb 2022 12:05] MySQL Verification Team
Hi,

Feel free to test but I do not believe there will be any changes since nothing wrt this is changed in the new version.

The issue here is I cannot reproduce this as I do not have your data. If you can make a reproducible test case with data it will be much easier. This is unrelated to the connector from what I see and is changed behavior on the server side.

Thanks

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.058 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.