提高空间MySQL查询的性能

Ste*_*son 4 mysql performance geospatial database-performance

我有一个查询返回所有记录,与我的 MySQL 5.7 数据库中的字段相比,按距固定点的距离排序POINT

举一个简单的例子,假设它看起来像这样:

SELECT shops.*, st_distance(location, POINT(:lat, :lng)) as distanceRaw 
FROM shops 
ORDER BY distanceRaw
LIMIT 50
Run Code Online (Sandbox Code Playgroud)

我的实际查询还必须执行一些连接才能获取结果的附加数据。

问题是,为了按距离对数据进行排序,需要计算数据库中每条记录(目前约为 100,000 条记录)的距离。

我无法缓存查询,因为它仅特定于那些原始坐标。

是否有办法限制必须计算的数据?例如,对附近商店进行可靠的粗略计算,例如lat+ lng? +/- 3 度。那么它只需要处理数据的子集?

如果有人有这种优化的经验,我希望得到一些建议,谢谢。

Sha*_*dow 5

是的,您可以在 where 标准中使用一些简单的近似来过滤掉那些明显超出半径的位置。这篇题为“SQL(MySQL、PostgreSQL、SQL Server)的快速最近位置查找器”的精彩博客文章描述了此类优化:

请记住,根据本文前面的背景信息,纬度为 111.045 公里。因此,如果我们的纬度列上有索引,我们可以使用这样的 SQL 子句来消除太北或太南而可能在 50 公里以内的点。

latitude BETWEEN latpoint - (50.0 / 111.045) AND latpoint + (50.0 / 111.045)

这个 WHERE 子句允许 MySQL 在计算半正矢距离公式之前使用索引省略大量纬度点。它允许 MySQL 对纬度索引执行范围扫描。

最后,我们可以使用类似但更复杂的 SQL 子句来消除太东或太西的点。该条款更为复杂,因为我们距离赤道越远,经度的距离就越小。这就是公式。

longitude BETWEEN longpoint - (50.0 / (111.045 * COS(RADIANS(latpoint)))) AND longpoint + (50.0 / (111.045 * COS(RADIANS(latpoint))))

因此,将所有内容放在一起,此查询会查找 (latpoint,longpoint) 50 公里边界框内的最近 15 个点。

上面描述了边界矩形的理论背景。