Finden Sie mit PostGIS die nächstgelegene Linie mit 2 Punkten?

9

Ich habe eine Tabelle t, die eine Spalte line_positionsvom Typ Zeile enthält. Bei 2 Punkten möchte ich die nächste Linie finden, die nah genug ist (weniger als 10 km) und die nicht zu nahe an einem Punkt vorbeiführt, den ich vermeiden möchte (mindestens 20 km). Derzeit benutze ich

SELECT t.*
FROM path t
WHERE
  ST_DWithin(ST_GeographyFromText('Point(69.835 22.596)'), t.line_positions, 10000, FALSE)  AND
  ST_DWithin(ST_GeographyFromText('Point(69.856 22.519)'), t.line_positions, 10000, false) AND
  NOT ST_DWithin(ST_GeographyFromText('Point(-79.804 9.141)'), t.line_positions, 20000, false)
ORDER BY
  ST_Distance(ST_GeographyFromText('Point(69.835 22.576)'), t.line_positions, false) +
  ST_Distance(ST_GeographyFromText('Point(69.856 22.519)'), t.line_positions, false)
  ASC
LIMIT 1

In ix_path_line_positionsder Spalte line_positions befindet sich ein Hauptindex .

Es funktioniert aber langsam, zwischen 3s und 30s für nur 100000 Zeilen in t.

erklären analysieren gibt:

Limit  (cost=9.95..9.95 rows=1 width=1432) (actual time=21729.253..21729.254 rows=1 loops=1)
   ->  Sort  (cost=9.95..9.95 rows=1 width=1432) (actual time=21729.251..21729.251 rows=1 loops=1)
         Sort Key: ((_st_distance('0101000020E61000003D0AD7A370755140FA7E6ABC74933640'::geography, line_positions, '0'::double precision, false) + _st_distance('0101000020E6100000105839B4C8765140BE9F1A2FDD843640'::geography, line_positions, '0'::double precision, false)))
         Sort Method: top-N heapsort  Memory: 26kB"
         ->  Index Scan using ix_path_line_positions on path t  (cost=0.28..9.94 rows=1 width=1432) (actual time=93.490..21710.562 rows=690 loops=1)
           Index Cond: ((line_positions && '0101000020E61000003D0AD7A3707551407F6ABC7493983640'::geography) AND (line_positions && '0101000020E6100000105839B4C8765140BE9F1A2FDD843640'::geography))
           Filter: (('0101000020E61000003D0AD7A3707551407F6ABC7493983640'::geography && _st_expand(line_positions, '10000'::double precision)) AND ('0101000020E6100000105839B4C8765140BE9F1A2FDD843640'::geography && _st_expand(line_positions, '10000'::double precision)) AND _st_dwithin('0101000020E61000003D0AD7A3707551407F6ABC7493983640'::geography, line_positions, '10000'::double precision, false) AND _st_dwithin('0101000020E6100000105839B4C8765140BE9F1A2FDD843640'::geography, line_positions, '10000'::double precision, false) AND ((NOT ('0101000020E6100000FA7E6ABC74F353C0D578E92631482240'::geography && _st_expand(line_positions, '20000'::double precision))) OR (NOT (line_positions && '0101000020E6100000FA7E6ABC74F353C0D578E92631482240'::geography)) OR (NOT _st_dwithin('0101000020E6100000FA7E6ABC74F353C0D578E92631482240'::geography, line_positions, '20000'::double precision, false))))
           Rows Removed by Filter: 15365
Planning time: 0.491 ms
Execution time: 21729.321 ms

Wie könnte ich es verbessern? Verwenden Sie stattdessen die Geometrieberechnung (aber meine Spur könnte mehrere tausend km umfassen. Werden die berechneten Entfernungen korrekt sein)? Verwenden des Operators <-> KNN (aber da ich auf der Summe von 2 Entfernungen bestelle, scheint er den Hauptindex sowieso nicht zu verwenden)?

Go4It
quelle
Sie können versuchen, den Parameter work_mem zu erhöhen , bevor Sie den Code ausführen. ZBSET work_mem TO '200MB';
Jaroslaw

Antworten:

1

Sind die beiden angegebenen Punkte immer innerhalb von 10 km voneinander entfernt? Wenn ja, könnten Sie versuchen, die beiden Punkte zu einer Linie zu machen und einen ST_DWithin anstelle von zwei auszuführen. Das kann die Dinge leicht verbessern.

SELECT t.*
FROM path t
WHERE
  ST_DWithin(ST_GeomFromText('LINESTRING(69.835 22.596,69.856 22.519)'), t.line_positions, 10000, FALSE)  
  NOT ST_DWithin(ST_GeographyFromText('Point(-79.804 9.141)'), t.line_positions, 20000, false)
ORDER BY
  ST_Distance(ST_GeographyFromText('Point(69.835 22.576)'), t.line_positions, false) +
  ST_Distance(ST_GeographyFromText('Point(69.856 22.519)'), t.line_positions, false)
  ASC
LIMIT 1
user92055
quelle
Nein, die 2 Punkte liegen nicht innerhalb von 10 km voneinander, sie können tausend km entfernt sein. Die Einschränkung ist, dass beide weniger als 10 km von der Linie entfernt sind, aber es könnte wirklich weit weg sein, da sich die Linien über tausend km erstrecken.
Go4It