我有一个查询,它返回所有记录,按固定点的距离排序,与MySQL 5.7数据库中的POINT
字段进行比较。
举一个简单的例子,让我们说它看起来像这样:
SELECT shops.*, st_distance(location, POINT(:lat, :lng)) as distanceRaw
FROM shops
ORDER BY distanceRaw
LIMIT 50
我的实际查询还必须进行一些连接才能获得结果的其他数据。
问题是,为了按距离对数据进行排序,需要计算数据库中每条记录的距离(目前大约有100,000条记录)。
我无法缓存查询,因为它只针对那些原始坐标。
是否有限制必须计算的数据?例如,附近商店的可靠粗略计算,比如lat
+ lng
+/- 3度?这样它只需要处理数据的子集吗?
如果有人对这种优化有任何经验,我会喜欢一些建议,谢谢。
答案 0 :(得分:3)
是的,您可以在标准中使用一些简单的近似值来过滤掉半径范围内显而易见的位置。标题为“SQL的最近位置查找器(MySQL,PostgreSQL,SQL Server)”的This great blog post描述了这样的优化:
请记住,根据我们在本文前面的背景信息, 纬度为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))))
所以,把这一切放在一起,这个查询找到了15分的neareast 它位于(纬度,长点)50km的边界框内。
以上描述了边界矩形的理论背景。