ค้นหาบรรทัดที่ใกล้เคียงที่สุดที่ให้ 2 คะแนนโดยใช้ PostGIS?


9

ฉันมีตาราง t ที่มีคอลัมน์line_positionsซึ่งเป็นประเภทบรรทัด ให้ 2 คะแนนฉันต้องการค้นหาเส้นที่ใกล้ที่สุดซึ่งอยู่ใกล้พอ (น้อยกว่า 10 กม.) และนั่นไม่ผ่านใกล้จุดที่ฉันต้องการหลีกเลี่ยง (ขั้นต่ำ 20 กม.) ปัจจุบันฉันใช้

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_positionsในคอลัมน์ line_positions

มันใช้งานได้ แต่ช้าระหว่าง 3 ถึง 30 วินาทีเพียง 100,000 แถวใน t

อธิบายการวิเคราะห์ให้:

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

ฉันจะปรับปรุงได้อย่างไร ใช้การคำนวณรูปทรงเรขาคณิตแทน (แต่เส้นทางของฉันอาจมีระยะทางหลายพันกิโลเมตรระยะทางที่คำนวณจะถูกต้อง) ใช้ <-> ตัวดำเนินการ KNN (แต่เมื่อฉันสั่งซื้อผลรวมระยะทาง 2 ทางดูเหมือนจะไม่ใช้ดัชนีกระทู้)


คุณสามารถลองเพิ่ม พารามิเตอร์work_memก่อนเรียกใช้งานโค้ด เช่นSET work_mem TO '200MB';
ยาโรสลัฟ

คำตอบ:


1

เป็นสองคะแนนที่ให้เสมอภายใน 10km จากกันและกัน ถ้าเป็นเช่นนั้นคุณสามารถลองสร้างจุดสองจุดเป็นเส้นและแสดงหนึ่ง ST_D ภายในแทนสองจุด ที่อาจปรับปรุงสิ่งต่าง ๆ เล็กน้อย

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

ไม่ 2 คะแนนไม่ได้อยู่ในระยะ 10 กม. จากกันพวกมันสามารถอยู่ห่างออกไปหลายพันกิโลเมตร ข้อ จำกัด คือทั้งสองน้อยกว่า 10 กม. ห่างจากเส้น แต่มันอาจอยู่ห่างไกลออกไปจริงๆเพราะเส้นทอดยาวหลายพันกิโลเมตร
Go4It
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.