【问题标题】:Way to improve performance in MySQL on POINT(lat, long)在 POINT(lat, long) 上提高 MySQL 性能的方法
【发布时间】:2023-03-03 10:55:01
【问题描述】:

我有一个应用程序需要查询一个带有经纬度坐标的表,这些坐标是使用 MYSQL 的 POINT 数据类型存储的。

我有一个存储函数,可以在给定 GPS 位置的给定半径内查找附近的纬度和经度。但是,我的表将包含数十万个条目,因此需要优化性能。

我已经编写了以下存储函数,但是从可能的 800,000 多行中返回大约 9,000 行大约需要 4.01 秒。有没有更好的方法来查找附近的 GPS 坐标?

这是我存储的函数:

    CREATE PROCEDURE `FindNearbyPoints`(
    IN RADIUS FLOAT,
    IN LAT FLOAT,
    IN LON FLOAT
)
BEGIN

    DECLARE EARTH_RADIUS FLOAT DEFAULT 3959;
    DECLARE maxLat FLOAT DEFAULT (LAT + DEGREES(RADIUS/EARTH_RADIUS));
    DECLARE minLat FLOAT DEFAULT (LAT - DEGREES(RADIUS/EARTH_RADIUS));

    /* compensate for degrees longitude getting smaller with increasing latitude*/
    DECLARE maxLon FLOAT DEFAULT (LON + DEGREES(RADIUS/EARTH_RADIUS/COS(RADIANS(LAT))));
    DECLARE minLon FLOAT DEFAULT (LON - DEGREES(RADIUS/EARTH_RADIUS/COS(RADIANS(LAT))));

    SELECT *, acos(sin(LAT)*sin(radians(X(Location))) + cos(LAT)*cos(radians(X(Location)))*cos(radians(Y(Location))-LON))*EARTH_RADIUS As D
    FROM (
        Select *
        From my_table
        Where X(Location)>minLat And X(Location)<maxLat
        And Y(Location)>minLon And Y(Location)<maxLon
    ) AS FIRST_CUT
    WHERE acos(sin(LAT)*sin(X(Location)) + cos(LAT)*cos(X(Location))*cos(Y(Location)-LON))*EARTH_RADIUS < RADIUS
    ORDER BY D;

END

我对该函数的大部分灵感来自:http://www.movable-type.co.uk/scripts/latlong-db.html

【问题讨论】:

  • 我天真的想法是你已经有很好的表现了。我很想看到改进它的建议。

标签: mysql performance latitude-longitude spatial-index


【解决方案1】:

我不确定您的数据库是如何设置的,但您可能会考虑使用 SPATIAL 索引,然后构造一个最小边界矩形来执行查询。通过边界框返回记录后,您可以快速按距离排序并消除半径之外的记录。我们在基因组学中使用这种索引,并且非常有效地定期查询十亿行的数据集。

mysql 文档中有关于空间索引的详细信息。

【讨论】:

    猜你喜欢
    • 2013-01-27
    • 2018-12-09
    • 1970-01-01
    • 2016-04-18
    • 1970-01-01
    • 2016-10-07
    • 2012-04-11
    • 2011-12-19
    相关资源
    最近更新 更多