POSTGIS:有效查询最近的点

时间:2019-03-05 15:00:40

标签: java postgresql postgis openstreetmap

我遇到以下问题:我有数百万个条目(地图中的点),并且我想将它们映射到最近的道路(OSM数据)。我在Java中实现了蛮力方法,在其中查询OSM数据库以找到最近的道路,然后将osm对象(road-id)分配给相应的条目。

但是这种方法效率低下,因为对每个条目的查询花费了将近1秒的时间,这使整个过程变得无穷无尽。

        PreparedStatement psWithLastPosition = this.conn.prepareStatement(sql);

        int i = 0;
        for (FCDEntry entry : dataset.getEntries()) {
            i += 1;
            String sqlQueryRoad = "SELECT osm_id,highway FROM planet_osm_roads ORDER BY " 
            + "ST_DISTANCE('SRID=4326;" 
            + ST_SetSRID.setSRID(new ST_MakePoint().createPoint(entry.getLongitude(),entry.getLatitude()), 4326).toString()
            + "'::geometry, " 
            + "ST_Transform(way::geometry,4326)) ASC LIMIT 1;";

            PreparedStatement psID = this.conn.prepareStatement(sqlQueryRoad);
            ResultSet rs = psID.executeQuery();
            String osm_id ="";
            while (rs.next()) {
                osm_id = rs.getString("osm_id");
            }

            log.info(osm_id);

            PreparedStatement ps = psWithLastPosition;
            ps.setString(1, entry.getAssetId());
            ...
            ps.setInt(18, Integer.valueOf(osm_id));
            ps.addBatch();

            // Execute every 1000 items
            if (i % 1000 == 0 || i == dataset.getEntries().size()) {
                log.info(i + "/" + dataset.getEntries().size());
                psWithLastPosition.executeBatch();
                psWithoutLastPosition.executeBatch();
            }

关于如何加快映射过程的任何想法吗?

1 个答案:

答案 0 :(得分:0)

该解决方案基于注释(感谢@JGH)。

我必须使用 <-> 运算符更改 st_distance 命令。现在,查询速度快了将近1000倍。

即,我现在的查询是:

String sqlQueryRoad = "SELECT osm_id,highway FROM planet_osm_roads ORDER BY " 
                    + "way <-> ST_Transform(ST_GeomFromText('POINT ("+ entry.getLongitude() + " " 
                    + entry.getLatitude()+ ")',4326), 3857) ASC LIMIT 1;";

由于某种原因,我没有与几何相关联的 way 列,而不是 geom 列(我发现的几乎所有帖子都具有geom列,最好猜测它们更改了OSM的osm2pgsql插入函数数据)。