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
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.
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)