【问题标题】:Organize a Mysql Database by Lat/Long More按 Lat/Long 组织 Mysql 数据库
【发布时间】:2012-09-11 04:39:35
【问题描述】:

我需要组织一个包含 7,000,000 条记录的 Mysql 数据库。它需要可以通过纬度/经度正方形进行查询,例如:22.54x -134.74x。它还需要通过monthname 进行分解。大约有 700 个可能的名称。

我不知道如何管理所有这些数据,以便该纬度/经度方格内的某人可以快速查询该月和纬度/经度方格内存在的names

我是否需要 10,000 多张桌子才能满足每一种纬度/经度的可能性?然后从那里分解成月份和名称?我的脑子快要爆炸了。

提前感谢您的帮助!

【问题讨论】:

    标签: mysql sql gis


    【解决方案1】:

    MySQL 提供spatial extensions that are specifically designed to efficiently deal with lat/long type problems

    如果您使用这些扩展,给定的行将包含一个地方的相关纬度和经度,并且查询将描述您感兴趣的几何边界。

    您的查询可能类似于

    SELECT name, AsText(location) FROM Points 
        WHERE X(location) > 0 AND X(location) < 1 AND
        Y(location) > 38 AND Y(location) < 39 
    

    这将选择位置(此处的位置是数据库中的空间列)经度介于 0 和 1 之间,纬度介于 38 和 39 之间的地点。

    【讨论】:

    • 我过去使用过这种东西,但问题是我需要在几秒钟内完成查询,而通过 700 万条记录需要更长的时间。我打算将数据分割成小的纬度/经度方块,并根据用户的纬度/经度,查询将通过一个小得多的表(我猜)。
    • 我使用 PostreSQL 空间扩展来处理非常大的数据集,并且查询是亚秒级的,具有适当的索引和硬件。如果你分成小方块,你必须自己做重叠处理。这并不容易。那时(2009 年)我选择 PostgreSQL 而不是 MySQL,因为空间扩展更加成熟。对于点在矩形中,MySQL 应该没问题。
    • 感谢您的帮助,埃里克。我刚刚尝试了您在上面提出的查询,它非常棒。只花了大约30秒。知道如何将其降低到一两秒吗?这是一个巨大的数据库!
    • 您的索引是什么样的?听起来你正在做一个表扫描。
    • 虽然听起来很愚蠢,但我不确定要使用什么索引。我没有。数据永远不会改变,所以索引不会成为问题,我只是不知道要一起索引什么。
    【解决方案2】:

    对于现代数据库,7,000,000 行并不多。如果您使用索引,您将显着缩短访问时间。不需要拆分表。我已经对 mySQL 和大约 100 万个位置进行了实验,并且没有使用空间扩展,并且对访问时间感到满意(仍然低于 1 秒)。

    你会做这样的事情:

    CREATE INDEX my_idx ON my_pos_table (month,name,lng,lat);
    

    我建议你试一试。没有什么比经验信息更好的了。还要观察您如何访问数据。也许你并不总是按月份和名称访问,所以你可以添加更多的索引,这只是插入行时的缺点。

    CREATE INDEX my_idx_2 ON my_pos_table (name,lng,lat);    
    CREATE INDEX my_idx_3 ON my_pos_table (lng,lat);
    

    希望对你有帮助。

    【讨论】:

    • 我永远不会更新这些表,所以创建大量索引是否正确?
    • @Patrick:对于给定的查询,MySQL 只会使用一个索引。由于在初始创建后不会产生更新索引的成本,并且考虑到磁盘空间很便宜,因此为每个主要查询优化索引是个好主意。
    【解决方案3】:

    你可以在这里找到有用的帖子:

    http://blog.jcole.us/2007/11/24/on-efficiently-geo-referencing-ips-with-maxmind-geoip-and-mysql-gis/

    我已将这篇文章作为一个超过 1.5 亿记录的项目的“起点”-myisam-,它运行良好

    顺便说一句,通常最好的方法是使用 GEOMETRYSPATIAL INDEX -only for myisam- 如下所示:

    • ALTER TABLE &lt;table&gt; ADD geom_point GEOMETRY NOT NULL ;
    • ALTER TABLE &lt;table&gt; ADD SPATIAL INDEX geom_point (geom_point) ;
    • UPDATE &lt;table&gt; SET geom_point = POINT(latitude, longitude);

    现在您可以使用如下查询在“正方形”中找到所有“名称”:

    SELECT * from <table> WHERE 
     MBRContains(GeomFromText('LineString(<lata> <lona>, <latb> <lonb>)'), geom_point)
    

    或按距离,如:

    $longitude = 8.449997;
    $latitude = 45.550003;
    $distance = 50; # km
    
    $point1 = $latitude + $distance / ( 111.1 / cos($latitude));
    $point2 = $longitude + $distance / 111.1;
    $point3 = $latitude - $distance / ( 111.1 / cos($latitude));
    $point4 = $longitude - $distance / 111.1;
    
    SELECT * from <table> WHERE 
     MBRContains(GeomFromText('LineString(<$point1> <$point2>, <$point3> <$point4>)'), geom_point)
    

    在你的测试台上试试 ;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      • 1970-01-01
      • 2020-08-05
      • 2014-04-05
      • 1970-01-01
      相关资源
      最近更新 更多