我有一个处理地理距离的查询。查询速度非常快,在我的224万行表上返回大约.1175秒。但是,我只需要最低距离,并且使用内置顺序太慢了。
有没有办法只跟踪一个最低限度的运行并给我这个?
例如,如果我有这些结果:
city a - 45km
city b - 48km
city c - 12km
我可以让它给我12公里,记住所有距离值都是计算出来的吗?
以下是对其进行排序的查询:
SELECT
City,
(
6371 *
acos(
cos(radians(-60.61384878636903)) *
cos(radians(st_x(location))) *
cos(radians(st_y(location)) -
radians(112.80061386895574)) +
sin(radians(-60.61384878636903)) *
sin(radians(st_x(location))))
) as distance
FROM table_name
HAVING distance < 5
ORDER BY distance ASC LIMIT 1
表结构如下:
id - int(12)
location - Point()
City - varchar(255)
问题在于,按标志的顺序需要太长时间来排序数据并获得最低数据。它可以保持最低运行速度,然后只是给我一个没有重大性能影响吗?
表包含,
2227851 - rows
spatial index on location
我得到的运行时间约为14秒,如果我使用订单,如果我不使用订单,我得到的时间为.1秒,这是我想要的运行时间或接近它
答案 0 :(得分:3)
Recomendations:
但如果你不想使用它
Set A = cos(radians(-60.61384878636903))
cos函数非常慢。X,Y
,则可以创建一个方格X +- 5, Y +- 5
并使用X,Y
上的常规索引答案 1 :(得分:1)
不,在查询级别上没有办法保持最低运行。
基本问题是,对于不同的纬度和经度值,最小距离会有所不同,搜索坐标在查询中作为文字提供。
一个选项是保留以前搜索坐标的表格,您之前查找的坐标,然后使用它来缩短执行其他查询的需要。首先搜索先前搜索的表格,然后从那里获得结果。
当然,如果向table_name
添加一行,您可能需要针对新行重新评估已保存的搜索坐标,并确定新行的距离是否比您拥有的更短保存。 (或者只是使整个商店无效,并为每次搜索重新填充。)
基本问题是必须为table_name
中的每一行评估“大圆距离”表达式。
对于不同的搜索值,该表达式的结果会有所不同 (经度和纬度)。
没有绕过每一行的计算,并且在所有这些结果中找到最低值。这将是一个“使用filesort”操作。使用LIMIT 1,我们希望MySQL不必对整个集合进行排序,并且只需要一次传递来识别最小值。
如果您可以限制需要评估的table_name
行数,并且您可以使用索引有效地排除它们......这将加快查询速度。
限制行数的一种方法是根据搜索纬度和经度定义“边界框”。并在WHERE子句中指定它。并让MySQL使用适当的索引。最粗糙的边界框可以定义为纬度的+/- dx度和搜索坐标的+/- dy度经度......例如
WHERE t.lat BETWEEN -60.613848 -4 AND -60.613848 +4
AND t.lon BETWEEN 120.800613 -8 AND 120.800613 +8
这不是一个理想的边界框,因为经度在赤道处的距离远远超过靠近两极的距离。
至于保持“最低运行”...无法使用当前查询完成。如果没有某些其他数据存储以某种方式键入搜索参数,就无法完成。