问题描述
我可以在同一硬件(带有 NVMe SSD 的 Windows 10)上运行 MysqL 5.7 和 8.0 版本。以下查询在 MysqL 5.7 下的执行速度比 MysqL 8.0 快 1000 多倍:
SELECT `oacode`,ST_asWKB(`shape`) as `shape` FROM
(SELECT * FROM oa_bdy WHERE seatname='Barnsley Central') AS `vtable`
WHERE MBRIntersects(`shape`,ST_GeomFromText('polyGON ((426519 410113,426519 4156675,432073 415667,432073 410113,426519 410113))',27700));
在 MysqL 5.7 上执行需要 0.016 秒,但在 MysqL 8.0 上需要 19.6 秒。
表使用 MyISAM,oa_bdy 表有 232,296 行,但只有 290 行与内部 WHERE 匹配。一个区别是查询中的“EXPLAIN”从两个版本中产生不同的结果。
MysqL | id | 选择类型 | 表 | 分区 | 类型 | possible_keys | 键 | key_len | 参考 | 行 | 过滤 | 额外 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
v5.7 | 1 | 简单 | oa_bdy | (NULL) | 范围 | 形状 | 形状 | 34 | (NULL) | 1406 | 10.00 | 在哪里使用 |
v8.0 | 1 | 简单 | oa_bdy | (NULL) | 全部 | (NULL) | (NULL) | (NULL) | (NULL) | 232296 | 10.00 | 在哪里使用 |
我对解决此问题的 MysqL 内部结构了解不够,但性能差异非常显着且有害。
大家有什么建议吗?
谢谢。
更新(2021 年 2 月 7 日)。感谢您对空间索引的评论。两个版本的模式是相同的(一个是另一个的副本)并且模式确实包含空间索引。
CREATE TABLE `oa_bdy` (
`shape` geometry NOT NULL,`oacode` varchar(9) NOT NULL,`seatname` varchar(43) DEFAULT NULL,PRIMARY KEY (`oacode`),SPATIAL KEY `shape` (`shape`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
一个问题似乎是 MysqL 8 中有一个新行为,它将忽略空间索引(用于查询优化目的),除非列具有已定义的 SRID(而不仅仅是单个单元格)。当8.0下的schema改成
CREATE TABLE `oa_bdy` (
`shape` geometry NOT NULL SRID 27700,SPATIAL KEY `shape` (`shape`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
那么8.0下的EXPLAIN与5.7匹配,8.0下的运行时间下降到0.391秒,仍然比MysqL 5.7慢24倍。
对于这种查询,有没有什么办法可以让 MysqL 8.0 下的运行时间与 MysqL 5.7 下的运行时间相似?
解决方法
您的旧数据库上肯定有一个索引,而新数据库上没有。由于新数据库缺少索引,MySQL 满足您查询的唯一方法是将表中的每一行与您的搜索条件进行比较。使用正确的索引,需要比较的行数要少得多。
在 5.7 和 8.0 上执行 SHOW CREATE TABLE oa_bdy
,并比较它们。老一辈肯定会提到一个或多个索引。
您可以创建一个索引来帮助处理您通过 doing this ....
向我们展示的查询CREATE SPATIAL INDEX x_oa_bdy_shape ON oa_bdy(shape);