我有一个相当简单的查询,该查询从两个联接表返回结果。该查询经常运行,最近我看到了一些非常慢的执行过程。我检查了slow_log
并能够提取以下信息:
# Time: 190307 12:10:47
# User@Host: root[root] @ [XX.XX.XX.XXX] Id: 12781339
# Query_time: 7.782994 Lock_time: 0.000049 Rows_sent: 51 Rows_examined: 909185
SET timestamp=1551960647;
SELECT
sg.id,
s.id as setting_id,
s.data_type,
s.setting_type,
s.name,
(case
when s.data_type = 'enum' AND sg.id then 1
when s.data_type = 'boolean' AND sg.value = '1' then 1
else 0 end) as enabled,
sg.value
FROM settings s
LEFT JOIN settings_values sg ON s.id = sg.setting_id AND sg.merchant_id = '1588' AND sg.branch_id IS NULL;
令人困惑的是,这两个表远远小于被检查的rows_examined的数量。 settings
仅包含51行,而settings_values
仅包含<20,000行。有趣的是,如果将它们相乘,您将得到大致rows_examined
的数字。
该查询在大多数情况下会在0.001秒内执行。我已经在本地环境中复制了查询,并且当查询在本地运行时,rows_examined
为51,所有其他变量都相同(也许流量除外)。所以我相信这只是偶尔发生。
我的问题是,谁能解释为什么rows_examined大于两个表的内容?
还有什么明显的原因会导致这种行为不规律地发生?
其他信息:
重要的是,结果始终要返回51行,这就是为什么JOIN是这样的原因。也就是说,有时settings_values
中不存在值,因此我需要返回默认数据。
这两个表的一些CREATE语句解释了索引等。
CREATE TABLE `settings` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`data_type` varchar(255) DEFAULT NULL,
`setting_type` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
CREATE TABLE `settings_values` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`merchant_id` int(10) DEFAULT NULL,
`branch_id` int(11) DEFAULT NULL,
`setting_id` int(10) DEFAULT NULL,
`value` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `merchant_id` (`group_id`),
KEY `setting_id` (`setting_id`),
KEY `branch_id` (`branch_id`),
CONSTRAINT `settings_values_settings_FK` FOREIGN KEY (`setting_id`) REFERENCES `settings` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
编辑:
当我对查询运行EXPLAIN语句时,得到以下结果:
+----+-------------+-------+------+-------------------------------+-----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------------------+-----------+---------+-------+------+-------------+
| 1 | SIMPLE | s | ALL | | | | | 51 | |
| 1 | SIMPLE | sg | ref | group_id,setting_id,branch_id | branch_id | 5 | const | 25 | Using where |
+----+-------------+-------+------+-------------------------------+-----------+---------+-------+------+-------------+