【问题标题】:MySql 8.0.11 spatial queries slow by a factor of 100000MySql 8.0.11 空间查询慢了 100000 倍
【发布时间】:2018-12-17 16:45:26
【问题描述】:

我们已将 MySql 5.7 数据库的副本迁移到 Amazon RDS 上的 MySql 8.0.11。在可能的情况下,一切都是相同的。包含几何数据的表已被修改,因此几何列被限制为 SRID 0 并重建空间索引。两个数据库上的执行计划相同,表明查询正在使用空间索引。

在 MySql 5.7 上,以下查询需要 0.001 秒,在 MySql 8 上需要 108 秒。在 MySql 8 上查看执行统计信息“发送数据”占 100% 的时间。为什么?

SELECT r.roadid                             
FROM geocoder.osm_road r
WHERE mbrintersects(ST_Buffer(ST_GEOMETRYFROMTEXT('Point(-1.91289 52.58260)',0),0.0005), r.geometry) 

我们有许多不同的空间查询,并且都表现得像这样,但特别是 MBRINTERSECTS 和 ST_INTERSECTS 似乎非常慢。更改为 ST_CONTAINS(在可能的情况下)会带来显着的改进(即上面需要 3 秒而不是 108 秒),但这不适用于许多查询,并且仍然比 5.7 慢很多。

Show Create Table for 5.7

CREATE TABLE `osm_road` (
  `roadid` bigint(20) NOT NULL,
  `reference` varchar(20) DEFAULT NULL,
  `name` varchar(100) DEFAULT NULL,
  `dictionary` longtext,
  `road_speed_limit` tinyint(4) unsigned NOT NULL,
  `road_speed_unitid` tinyint(1) NOT NULL,
  `road_type` tinyint(4) NOT NULL,
  `is_toll_road` bit(1) NOT NULL DEFAULT b'0',
  `is_one_way` bit(1) NOT NULL DEFAULT b'0',
  `countryid` smallint(6) DEFAULT NULL,
  `geometry` geometry NOT NULL,
  `datemodified` datetime DEFAULT CURRENT_TIMESTAMP,
  `datecreated` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`roadid`),
  UNIQUE KEY `id_roadid` (`roadid`),
  SPATIAL KEY `ix_road_geometry` (`geometry`),
  KEY `ix_road_reference` (`reference`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AVG_ROW_LENGTH=207


Show Create Table for 8.0.11

CREATE TABLE `osm_road` (
  `roadid` bigint(20) NOT NULL,
  `reference` varchar(20) DEFAULT NULL,
  `name` varchar(100) DEFAULT NULL,
  `dictionary` longtext,
  `road_speed_limit` tinyint(4) unsigned NOT NULL,
  `road_speed_unitid` tinyint(1) NOT NULL,
  `road_type` tinyint(4) NOT NULL,
  `is_toll_road` bit(1) NOT NULL DEFAULT b'0',
  `is_one_way` bit(1) NOT NULL DEFAULT b'0',
  `countryid` smallint(6) DEFAULT NULL,
  `geometry` geometry NOT NULL /*!80003 SRID 0 */,
  `datemodified` datetime DEFAULT CURRENT_TIMESTAMP,
  `datecreated` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`roadid`),
  UNIQUE KEY `id_roadid` (`roadid`),
  KEY `ix_road_reference` (`reference`),
  SPATIAL KEY `ix_road_geometry` (`geometry`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AVG_ROW_LENGTH=207

显示来自 osm_road (5.7) 的索引

Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment
osm_road,0,PRIMARY,1,roadid,A,18973144,NULL,NULL,,BTREE,,
osm_road,1,ix_road_geometry,1,geometry,A,18973154,32,NULL,,SPATIAL,,
osm_road,1,ix_road_reference,1,reference,A,199900,NULL,NULL,YES,BTREE,,

显示来自 osm_road (8.0.11) 的索引

Table,Non_unique,Key_name,Seq_in_index,Column_name,Collation,Cardinality,Sub_part,Packed,Null,Index_type,Comment,Index_comment,Visible
osm_road,0,PRIMARY,1,roadid,A,16194921,NULL,NULL,,BTREE,,,YES
osm_road,1,ix_road_reference,1,reference,A,86215,NULL,NULL,YES,BTREE,,,YES
osm_road,1,ix_road_geometry,1,geometry,A,16194921,32,NULL,,SPATIAL,,,YES

显示全局状态 (8.0.11) Click Here

显示全局变量 (8.0.11) Click Here

-- 添加于 2019-01-27 -----------------

EXPLAIN SELECT r.roadid FROM geocoder.osm_road r WHERE mbrintersects(ST_Buffer(ST_GEOMETRYFROMTEXT('Point(-1.91289 52.58260)',0),0.0005), r.geometry); 

返回:

select_type:   Simple
table:         r
partitions:    null
possible_keys: ix_road_geometry
key:           ix_road_geometry
key_len:       34
ref:           null
rows:          1
filtered:      100
Extra:         Using where

【问题讨论】:

  • 为两个 MySQL 服务器发布 SHOW CREATE TABLE <table> 输出。还为我们提供两台服务器的EXPLAIN <query>,我们想验证..
  • "MySql 5.7 以下查询需要 0.001s'" 这听起来像 query cache 对我来说或者为 innodb buffers 配置更好的 MySQL 5.7 服务器。除了 MySQL 8.0.11 服务器安装是新的,所以它是“冷”运行的,而不是一个长期存在的带有 innodb 缓存的“暖”服务器
  • 两个数据库都很冷,没有生产数据库。查看原始帖子以获取“显示创建表”信息
  • “两个数据库都很冷,没有生产数据库”我想确定缓存没有涉及到这个。你能也分享一下解释吗?
  • 我还要补充一点,这个表中只有 32,000 行。有关说明的详细信息,请参阅现在“已编辑”的原始帖子

标签: mysql performance spatial


【解决方案1】:

MBRIntersectsST_Intersects 在 MySQL 8.0 中被破坏(在 8.0.15 中测试)并且与 MySQL 5.7 相比慢了 10 倍以上。对我来说,禁用空间索引(使用IGNORE INDEX,强制进行全表扫描,在一定程度上加快了我的查询速度。请参阅此错误报告https://bugs.mysql.com/bug.php?id=94655

【讨论】:

  • 这应该在 MySql 8.0.20 中修复。由于我们使用的是 AWS,因此在 AWS 发布这个小更新之前我不会知道,这可能需要 12 个月。
【解决方案2】:

我遇到了类似的问题,答案是确保空间列包含 SRID。见https://mysqlserverteam.com/upgrading-to-mysql-8-0-with-spatial-data/。之后,查询开始使用空间索引,这是他们之前没有使用过的

【讨论】:

  • 很高兴这对你有用。我们已经设置了 SRID,但问题仍然存在于最简单的查询中。一切都指向 MySql v8 中的一个严重错误,已报告。
  • 这解决了我在 MySQL 8 中使用其他空间函数的问题,但我不能谈论原始发布者的问题。因为这是帮助我的线程(和答案!),所以让我为其他前来寻找的人详细说明一下。 1. 如果还没有,请将您的表更改为 InnoDB。 2. 删除任何使用该列的现有索引。 3.更改列的SRID。 (示例语法:ALTER TABLE myTable MODIFY COLUMN myColumn GEOMETRY SRID 4326 NOT NULL)。 4. 重新创建任何索引。
  • 这是有用的信息,需要完成(在我们的例子中)。但这并没有改变这样一个事实,即版本 8 中存在一个严重的错误,它导致最基本的地理空间查询在大型数据集上运行得非常慢(与 MySql 5.7 和 Postgres 相比)。这已被认为是一个问题。 bugs.mysql.com/bug.php?id=94655
猜你喜欢
  • 2015-01-03
  • 2021-02-13
  • 2016-04-21
  • 1970-01-01
  • 2018-12-22
  • 2019-12-01
  • 2020-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多