为什么MySQL查询要花很长时间执行,过滤意味着什么?
我有一个查询需要很长时间才能执行,而在解释计划中过滤意味着什么 下面是MySQL查询,解释一个表的计划和结构,版本是MySQL V8.0为什么MySQL查询要花很长时间执行,过滤意味着什么?,mysql,optimization,mysql-8.0,Mysql,Optimization,Mysql 8.0,我有一个查询需要很长时间才能执行,而在解释计划中过滤意味着什么 下面是MySQL查询,解释一个表的计划和结构,版本是MySQL V8.0 SELECT `responses`.* FROM `responses` WHERE `responses`.`survey_id` = 196690 AND (responses.time >= '2017-01-01 08:00:00') AND (responses.time <= '2020-10-13 13:00:58')
SELECT `responses`.*
FROM `responses`
WHERE `responses`.`survey_id` = 196690 AND (responses.time >= '2017-01-01 08:00:00') AND (responses.time <= '2020-10-13 13:00:58')
ORDER BY `responses`.`id` ASC
LIMIT 500 OFFSET 0;
CREATE TABLE `responses` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`survey_id` int(10) NOT NULL,
`token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`time` datetime NOT NULL,
`ip_address` int(15) unsigned NOT NULL,
`identity` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`user_agent` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`completed` tinyint(1) DEFAULT NULL,
`completed_time` datetime DEFAULT NULL,
`referrer` tinytext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
`page` tinytext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
`visible` tinyint(1) DEFAULT '0',
`mail_sent` tinyint(1) DEFAULT '0',
`anonuuid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`metadata` json DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `survey_id` (`survey_id`),
KEY `time` (`time`),
KEY `index_responses_on_survey_id_and_time` (`survey_id`,`time`),
KEY `survey_id_2` (`survey_id`,`token`),
KEY `survey_id_3` (`survey_id`,`mail_sent`)
)ENGINE=InnoDB AUTO_INCREMENT=204788658 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC
explain
SELECT `responses`.*
FROM `responses`
WHERE `responses`.`survey_id` = 196690 AND (responses.time >= '2017-01-01 08:00:00') AND (responses.time <= '2020-10-19 13:01:00')
ORDER BY `responses`.`id` ASC
LIMIT 500 OFFSET 0\G
- 将
替换为TINYTEXT
。文本列虽然本质上与VARCHAR相同,但有一些微妙的额外开销VARCHAR(…)
- 将
大小缩小为“合理”大小VARCHAR
- 当您同时拥有
和索引(调查id)
时,请去掉前者。不仅没有必要,优化器有时会在后者更好的时候选择前者索引(调查id…)
- 将
更改为按id排序
(如果它没有太多地干扰所需的结果)。可能优化器认为按时间排序
比使用orderbyid
运行查询更好。将此更改为“订单依据”将防止出现这种情况。我怀疑该表的大部分都包含在该时间范围内,这有助于混淆优化器INDEX(survey\u id,time)
PRIMARY KEY (`id`),
KEY `survey_id` (`survey_id`),
KEY `time` (`time`),
KEY `index_responses_on_survey_id_and_time` (`survey_id`,`time`),
KEY `survey_id_2` (`survey_id`,`token`),
KEY `survey_id_3` (`survey_id`,`mail_sent`)
-->
这将迫使优化器使用最佳索引,并避免在索引的BTree和数据的BTree之间反弹500次
(如上所述,通过更改订单)
我不知道是否值得保留这两个索引:(调查id,令牌)
和(调查id,邮件发送)
“Filtered”是对保留行的百分比的粗略估计。我很少发现它有什么用处
我看到您正在使用OFFSET
。这是否意味着您将“分页”?如果是这样,还有更多的问题需要讨论。长时间是多少时间?嗨,nacho,执行需要10分钟以上
PRIMARY KEY (`id`),
KEY `survey_id` (`survey_id`),
KEY `time` (`time`),
KEY `index_responses_on_survey_id_and_time` (`survey_id`,`time`),
KEY `survey_id_2` (`survey_id`,`token`),
KEY `survey_id_3` (`survey_id`,`mail_sent`)
PRIMARY KEY (`survey_id`,`time`, `id`), -- 'cluster' primarily on survey_id
KEY(id), -- to keep AUTO_INCREMENT happy
KEY `time` (`time`),