这是我正在使用的技术堆栈,Java 11, JOOQ 3.12.1和MYSQL 8.0.28(从5.7.28升级),连接池(30)和引擎InnoDB。
下面是我在MySQL 5.7.28中使用JOOQ在15秒内成功执行的示例查询。IN查询大约需要60k个id。现在MYSQL 8.0.28的查询大约需要92秒。
select `id`, `name`, `description` from `ex_table` where `id` in (?,?,?,?,?,....);
就信息而言,我已经使用了mariadb和mysql连接器,所以我可以得出结论,连接器没有问题。
[编辑]
show create table ex_table;
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ex_table | CREATE TABLE `ex_table` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`description` varchar(1000) DEFAULT NULL,
`stack_id` mediumint unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unq_node` (`name`,`stack_id`),
KEY `idx_stack` (`stack_id`)
) ENGINE=InnoDB AUTO_INCREMENT=72279 DEFAULT CHARSET=utf8mb3 |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)
SHOW TABLE STATUS WHERE name LIKE 'ex_table';
+------------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment |
+------------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| ex_table | InnoDB | 10 | Dynamic | 60272 | 43 | 2637824 | 0 | 5275648 | 4194304 | 72279 | 2022-06-30 07:10:14 | NULL | NULL | utf8_general_ci | NULL | | |
+------------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
1 row in set (0.02 sec)
explain select `id`, `name`, `description`, `stack_id` from `ex_table` where `id` in (1,2,3,4,5,6,7,8,9,10);
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | SIMPLE | ex_table | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 10 | 100.00 | Using where |
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)
Running Full Query with Explain:
+----+-------------+------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| 1 | SIMPLE | ex_table | NULL | ALL | PRIMARY | NULL | NULL | NULL | 60272 | 50.00 | Using where |
+----+-------------+------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
1 row in set, 2 warnings (0.51 sec)
SLOW QUERY LOG
# Time: 2022-07-18T14:38:02.110872-00:00
# User@Host: user[host] @ localhost [127.0.0.1]
# Schema: dbname Last_errno: 0 Killed: 0
# Query_time: 33.762935 Lock_time: 0.075141 Rows_sent: 60052 Rows_examined: 60052 Rows_affected: 0 Bytes_sent: 1619164
use dbname;
SET timestamp=1658155048;
select `dbname`.`ex_table`.`id`, `dbname`.`ex_table`.`name`, `dbname`.`ex_table`.`description`, `dbname`.`ex_table`.`stack_id` from `dbname`.`ex_table` where `dbname`.`ex_table`.`id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, ... );
[编辑2]优化器跟踪
{
"steps": [
{
"statement_parameters": [
"LONGLONG",
"LONGLONG",
"LONGLONG",
"LONGLONG",
"LONGLONG",
"LONGLONG",
"LONGLONG",
……,
…..,
]
},
{
"join_optimization": {
"select#": 1,
"steps": [
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "(`ex_table`.`id` in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101, …))”,
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(`ex_table `.`id` in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,…))”
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "(`ex_table `.`id` in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,…))”,
"final_table_condition ": "(`ex_table`.`id` in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,..))”
}
]
},
{
"refine_plan": [
{
"table": "`ex_table`”
}
]
}
]
}
},
{
"join_execution": {
"select#": 1,
"steps": [
]
}
}
]
}
Explain format=json SELECT ...
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "6047.05"
},
"table": {
"table_name": “ex_table”,
"access_type": "ALL",
"possible_keys": [
"PRIMARY"
],
"rows_examined_per_scan": 60068,
"rows_produced_per_join": 30034,
"filtered": "50.00",
"cost_info": {
"read_cost": "3043.65",
"eval_cost": "3003.40",
"prefix_cost": "6047.05",
"data_read_per_join": "108M"
},
"used_columns": [
"id",
"name",
"description",
“stack”_id
],
"attached_condition": "(`db`.`ex_table`.`id` in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,….))”
}
}
}
我以前遇到过这种情况,主要是因为两个版本的查询优化器之间的差异,当然这与innodb的几个参数有关。