POSTGIS: эффективный запрос на ближайшую точку - PullRequest
0 голосов
/ 05 марта 2019

У меня следующая проблема: у меня есть миллионы записей (точек на карте), и я хочу сопоставить их с ближайшей дорогой (данные 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 голосов
/ 06 марта 2019

Решение основано на комментариях (спасибо @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;";

По какой-то причине вместо geom столбца у меня был way *Столбец 1015 *, связанный с геометрией (почти все сообщения, которые я обнаружил, имели столбец geom, вероятно, они изменили функцию вставки osm2pgsql для данных OSM).

...