与 5.7 相比,MySQL 8.0.32 按 POINT() 列进行分组且未使用索引速度较慢

问题描述 投票:0回答:1

我们最近从 MySQL 5.7 更新到 8.0.32,并且不得不重新设计数据库 POINT 列,该列以前使用基于前缀的 (??) 索引非常快,我相信 MySQL 8.0.x 不支持该索引。

我将该列更改为仅包含“SRID 4326”的列,并为其指定了空间索引。

在 MySQL 5.7 中,我从未考虑是否使用了 B 树索引,因为查询都相当快。

现在,运行过去“快速”的等效查询大约需要 18 秒左右。我的查询格式为:

SELECT
  ST_Latitude(granularity_30) as lat,
  ST_Longitude(granularity_30) as lng
FROM
  `GeoPriceCache`
WHERE
  MBRContains(ST_GeomFromText('Polygon((
    -64.36807421875 56.379500183529,
    -64.36807421875 18.086774255995,
    -132.79092578125 18.086774255995,
    -132.79092578125 56.379500183529,
    -64.36807421875 56.379500183529
    ))', 4326, 'axis-order=long-lat'), granularity_30)
GROUP BY granularity_30;

该表包含数十万条记录,这应该收集其中的大部分记录,分组后放入约 250 行中。

我不确定我是否在不知不觉中更改了我的系统的某些内容(这完全是预料之中的),或者我是否遗漏了某些内容。

我很困惑为什么,如果在上面的查询上运行 EXPLAIN,它会将我的

granularity_30
列标识为具有“possible_key”,但不使用它。

如果我反转

MBRContains()
,使点排在第一位,
Polygon()
排在第二位,它声称它将使用该密钥,但是当然,我的记录的单个密钥都不包含该多边形,所以...我可以不要那样做。 :)

编辑: 表的 DDL:

CREATE TABLE `GeoPriceCache` (
  `item_id` bigint unsigned NOT NULL,
  `granularity_30` point NOT NULL /*!80003 SRID 4326 */ COMMENT 'This item''s cluster point when viewing at a moderate zoom level.',
  `granularity_40` point NOT NULL /*!80003 SRID 4326 */ COMMENT 'This item''s cluster point when zoomed in to a high zoom level.',
  `granularity_50` point NOT NULL /*!80003 SRID 4326 */ COMMENT 'This item\\s cluster point when zoomed in to a very high zoom level.',
  UNIQUE KEY `geopricecache_item_id_unique` (`item_id`),
  SPATIAL KEY `geopricecache_granularity_50_spatialindex` (`granularity_50`),
  SPATIAL KEY `geopricecache_granularity_40_spatialindex` (`granularity_40`),
  SPATIAL KEY `geopricecache_granularity_30_spatialindex` (`granularity_30`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin

如果我使用

FORCE INDEX (geopricecache_granularity_30_spatialindex)
,它确实使用索引,但速度并不快。 (实际上,可能会快1-2秒?也许只是一个异常?)

mysql mysql-8.0 spatial-query spatial-index
1个回答
0
投票

我最终在 dba.stackexchange.com 问了一个[被认为是不相关的]问题,该问题的解决方案也解释了这一点。

要点是这样的:

如果服务器中没有足够的资源来执行此操作,则索引(...至少是这个空间索引。)似乎并未固有地填充(或者由于某种原因而无法使用)。

我修改了以下三个全局变量:

max_heap_table_size 设置为 64M tmp_table_size设置为64M innodb_buffer_pool_size 设置为 4G(至少目前在我的本地 Docker MySQL 服务器中)

最后,索引可以(并且已经)被使用!

© www.soinside.com 2019 - 2024. All rights reserved.