Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么MySQL查询要花很长时间执行,过滤意味着什么?_Mysql_Optimization_Mysql 8.0 - Fatal编程技术网

为什么MySQL查询要花很长时间执行,过滤意味着什么?

为什么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')

我有一个查询需要很长时间才能执行,而在解释计划中过滤意味着什么

下面是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') 
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`),