PostGIS kullanarak 2 puan verilen en yakın hattı mı buldunuz?


9

Ben line_positionstür satır olan bir sütun içeren bir tablo t var . 2 puan verildiğinde yeterince yakın (10km'den az) ve kaçınmak istediğim bir noktaya (minimum 20km) çok yakın geçmeyen en yakın hattı bulmak istiyorum. Şu anda kullanıyorum

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

ix_path_line_positionsLine_positions sütununda bir öz dizin vardır .

T sadece 100000 satır için 3s ve 30s arasında yavaş çalışır.

açıklamak analiz verir:

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

Nasıl geliştirebilirim? Bunun yerine geometri hesaplamasını kullanmak (ancak parkurum binlerce kilometreyi bulabilir, hesaplanan mesafeler doğru mu?) <-> KNN operatörünü kullanma (ancak 2 mesafenin toplamını sipariş ettiğim için, yine de gist dizinini kullanmıyor gibi görünüyor)?


Kodu çalıştırmadan önce work_mem parametresini artırmayı deneyebilirsiniz . Ör.SET work_mem TO '200MB';
Yaroslav

Yanıtlar:


1

Verilen iki nokta her zaman birbirinin 10 km yakınında mıdır? Öyleyse, iki noktayı bir çizgi oluşturmayı ve iki yerine bir ST_DWithin gerçekleştirmeyi deneyebilirsiniz. Bu işleri biraz iyileştirebilir.

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

Hayır, 2 puan birbirinin 10 km yakınında değil, bin km uzakta olabilir. Kısıtlama, her ikisinin de hattan 10 km'den daha az bir mesafede olması, ancak hatların bin km'yi kapsadığı için gerçekten çok uzakta olabileceğidir.
go4it
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.