优化SQL查询以提高效率

时间:2016-04-01 22:23:00

标签: mysql database-performance query-performance

我有一个处理地理距离的查询。查询速度非常快,在我的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秒,这是我想要的运行时间或接近它

2 个答案:

答案 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 

这不是一个理想的边界框,因为经度在赤道处的距离远远超过靠近两极的距离。

至于保持“最低运行”...无法使用当前查询完成。如果没有某些其他数据存储以某种方式键入搜索参数,就无法完成。