| 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: | |
| 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 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

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)