我们最近从 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秒?也许只是一个异常?)
我最终在 dba.stackexchange.com 问了一个[被认为是不相关的]问题,该问题的解决方案也解释了这一点。
要点是这样的:如果服务器中没有足够的资源来执行此操作,则索引(...至少是这个空间索引。)似乎并未固有地填充(或者由于某种原因而无法使用)。
我修改了以下三个全局变量:
max_heap_table_size 设置为 64M tmp_table_size设置为64M innodb_buffer_pool_size 设置为 4G(至少目前在我的本地 Docker MySQL 服务器中)
最后,索引可以(并且已经)被使用!