【发布时间】:2019-01-27 08:28:21
【问题描述】:
我完成以下 mysql 查询大约需要 55 秒
SELECT this_.id AS y0_ FROM event this_
INNER JOIN member m1_ ON this_.member_id=m1_.id
INNER JOIN event_type et2_ ON this_.type_id=et2_.id
WHERE m1_.submission_id=40646 AND et2_.name IN ('Salary')
ORDER BY m1_.ni_number ASC, m1_.ident1 ASC, m1_.ident2 ASC, m1_.ident3 ASC, m1_.id ASC, et2_.name ASC LIMIT 15;
如果我删除了“event_type”表的连接/位置/顺序,那么查询将在 1 秒内运行。
因此,我加入“event_type”表显然有些问题,但是在另一个具有类似数据库卷的数据库中的类似查询运行得非常好。所以我怀疑这个 1 数据库有问题。
'event'表的'show create table'是:
Create Table: CREATE TABLE `event` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`data_size` bigint(20) DEFAULT NULL,
`encoded_data` mediumblob,
`last_updated` datetime NOT NULL,
`member_id` bigint(20) NOT NULL,
`parent_event_id` bigint(20) DEFAULT NULL,
`status` varchar(255) DEFAULT NULL,
`type_id` bigint(20) NOT NULL,
`updated_by` varchar(255) NOT NULL,
`failed_workflow_case` varchar(255) DEFAULT NULL,
`failed_workflow_task` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK5C6729A2434DA80` (`member_id`),
KEY `FK5C6729AE4E22C6E` (`type_id`),
KEY `IND_parent_event_id` (`parent_event_id`),
CONSTRAINT `FK5C6729A2434DA80` FOREIGN KEY (`member_id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK5C6729AE4E22C6E` FOREIGN KEY (`type_id`) REFERENCES `event_type` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=46241198 DEFAULT CHARSET=latin1
查询的解释是:
+----+-------------+-------+------------+--------+-------------------------------------+-------------------+---------+--------------------------+------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+-------------------------------------+-------------------+---------+--------------------------+------+----------+----------------------------------------------+
| 1 | SIMPLE | et2_ | NULL | ref | PRIMARY,IND_name | IND_name | 257 | const | 1 | 100.00 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | this_ | NULL | ref | FK5C6729A2434DA80,FK5C6729AE4E22C6E | FK5C6729AE4E22C6E | 8 | iconnect.et2_.id | 3303 | 100.00 | NULL |
| 1 | SIMPLE | m1_ | NULL | eq_ref | PRIMARY,IND_submission_id | PRIMARY | 8 | iconnect.this_.member_id | 1 | 5.00 | Using where |
+----+-------------+-------+------------+--------+-------------------------------------+-------------------+---------+--------------------------+------+----------+----------------------------------------------+
“事件”表中的索引是:
+-------+------------+---------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+---------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| event | 0 | PRIMARY | 1 | id | A | 14307622 | NULL | NULL | | BTREE | | |
| event | 1 | FK5C6729A2434DA80 | 1 | member_id | A | 4680601 | NULL | NULL | | BTREE | | |
| event | 1 | FK5C6729AE4E22C6E | 1 | type_id | A | 4360 | NULL | NULL | | BTREE | | |
| event | 1 | IND_parent_event_id | 1 | parent_event_id | A | 114404 | NULL | NULL | YES | BTREE | | |
+-------+------------+---------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
从这里跳出来的是: 1. 为什么 EXPLAIN 会经过 3303 行和 FK5C6729AE4E22C6E 索引? 2. 为什么'event_type'表只有17行时,FK5C6729AE4E22C6E索引的基数是4360?这种不正确的基数会影响查询优化器吗?
我已经对 'event' 和 'event_type' 做了一个分析表,这没有任何区别。
有什么建议吗?
使用相同数据(从转储文件加载)从其他服务器执行计划:
+----+-------------+-------+------------+------+-------------------------------------+-------------------+---------+-----------------+-------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+-------------------------------------+-------------------+---------+-----------------+-------+----------+----------------------------------------------+
| 1 | SIMPLE | et2_ | NULL | ALL | PRIMARY | NULL | NULL | NULL | 17 | 10.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | m1_ | NULL | ref | PRIMARY,IND_submission_id | IND_submission_id | 8 | const | 27992 | 100.00 | NULL |
| 1 | SIMPLE | this_ | NULL | ref | FK5C6729A2434DA80,FK5C6729AE4E22C6E | FK5C6729A2434DA80 | 8 | iconnect.m1_.id | 3 | 11.11 | Using where |
+----+-------------+-------+------------+------+-------------------------------------+-------------------+---------+-----------------+-------+----------+----------------------------------------------+
【问题讨论】:
-
a) 统计数据是估计值。 MySQL 对随机部分进行采样(取决于您的配置)并进行推断;因子 200 确实会对索引选择产生影响 b) 最相关的表似乎是
member(特别是submission_id或ni_number上的索引),而不是event。请添加该表,并确保它们在两台服务器上相同 c) 因为您似乎已经在另一台服务器上拥有正确的执行计划:请添加它。然后尝试(通过例如强制索引)。弄清楚为什么 MySQL 自己没有找到该计划将是第二步。 -
感谢更新;该执行计划与我的预期相符;每个提交 ID 的行数是否正确?在这种情况下,错误的统计数据似乎是问题所在(3k 27k),我认为它们在另一台服务器上(更多)是正确的。检查
innodb_stats_persistent_sample_pages(假设@987654332 @ 已启用);我假设默认值(20)应该没问题,但请确保没有人降低或禁用它。无论如何,当前值似乎太低,所以增加它并再次尝试analyze。 -
有 43k 个事件记录,用于 14k 个指定了 submit_id 的成员,其中 14k 个事件记录用于名称 arg 指定的 event_type 记录。所以我的查询应该找到 14k 个结果,但只返回前 15 个。我无法理解这与任一执行计划中的行返回有何关系。
-
innodb 统计数据被持久化,两台服务器上的 sample_pages 都是 20。
标签: mysql