กำลังดำเนินการค้นหาขอบเขตกล่องใน PostGIS? [ปิด]


22

ผมมีตาราง PostgreSQL มีเกือบ 2 ล้านแถวด้วยความยาวลาดพร้าวเขตข้อมูลในแบบฟอร์มcoordinatesPOINT(-73.4938 33.2405)

สมมติว่ามีดัชนีเชิงพื้นที่ในเขตข้อมูลนั้นวิธีที่มีประสิทธิภาพมากที่สุดและเร็วที่สุดในการเลือกแถวทั้งหมดภายในกล่องขอบเขตโดยพลการคืออะไร

กล่องเป็นเหมือน,SW long-lat: -74.0042 40.7688NE long-lat: -73.8809 40.7984


พิกัดที่เก็บไว้ของคุณมีความยาวแลตหรือเป็นตาราง (X, Y) หรือไม่
Martin F

1
คณิตศาสตร์อย่างง่ายจะทำที่นี่ ... ถ้า point.x ใหญ่กว่า SW.x และเล็กกว่า NE.x และ point.y ใหญ่กว่า SW.y และเล็กกว่า NE.y ในเวลาเดียวกันจุดนั้นจะอยู่ภายใน MBR ฉันไม่ทราบว่าจะเร็วกว่าการใช้แบบสอบถามเชิงพื้นที่หรือไม่ คุณคิดจะลองไหม
Michal Zimmermann

@zimmi: เขาไม่ได้ระบุว่ารายการนั้นเป็นเพียงแค่จุด มันอาจเป็นรูปทรงเรขาคณิตที่ซับซ้อน
Martin F

พวกเขาเป็นเพียงคะแนน แต่ ;-) พวกมันจะยาวในรูปแบบ POINT (-73.4938 33.24059) ที่เก็บไว้เป็น WKB
Avishai

ฉันแก้ไข Q (และ A) เพื่อสะท้อนข้อมูลนั้น :-)
Martin F

คำตอบ:


24

สมมติว่าข้อ จำกัด ของขอบเขตที่กำหนดนั้นอยู่ในระบบการอ้างอิงเชิงพื้นที่เดียวกับพิกัดที่เก็บไว้และคุณรู้ว่าผู้ประกอบการอวกาศ (ปริภูมิหรืออยู่ภายใน) คุณต้องการ:

SELECT *
FROM   my_table
WHERE  coordinates 
    && -- intersects,  gets more rows  -- CHOOSE ONLY THE
    @ -- contained by, gets fewer rows -- ONE YOU NEED!
    ST_MakeEnvelope (
        xmin, ymin, -- bounding 
        xmax, ymax, -- box limits
        my_srid)

อีกทางเลือกหนึ่งหากคุณต้องการเสียง "มี" (แทนที่จะเป็น "มีอยู่") WHEREประโยคควรพลิก:

WHERE  ST_MakeEnvelope (...)
    ~ -- contains, gets same fewer rows 
    coordinates 

PS: ป.ร. ให้ไว้ (โดย OP หลังจากที่ถูกโพสต์ดังกล่าวข้างต้น) ที่บันทึกเป็นจุดง่ายผมคิดว่าความแตกต่างระหว่าง "ปริภูมิ" และ "บรรจุ" กลายเป็นที่ลึกซึ้งมากส่งผลกระทบต่อเพียงจุดบนขอบของช่องขอบ


นั่นเป็นจุดที่ดี ควรมีส่วนประกอบอย่างดีเนื่องจากคุณจะไม่สามารถเห็นเครื่องหมายบนแผนที่ได้หากอยู่ในขอบเขต (เช่นอาจเป็นเบราว์เซอร์โครม)
Avishai

What's the fastest ...?: OP
Magno C

ระวัง: &&และ@ดูเหมือนจะไม่ทำงานเมื่อตัดกันด้วยรูปหลายเหลี่ยมเรขาคณิต ในกรณีนี้ให้ใช้ST_Intersects(latlng_column,ST_GeomFromText('Polygon ((...))',4326))หรือมิฉะนั้นST_Contains
Alex

4
SELECT ST_Y(the_geom) AS latitude, ST_X(the_geom) as longitude
from units u where the_geom && ST_MakeEnvelope(left, bottom, right, top, 4326)

1
ไม่จำเป็นต้องบอกว่า 4326 เป็น SRID
Magno C

2

เห็นได้ชัดว่าฉันไม่มีคะแนนเพียงพอที่จะเพิ่มความคิดเห็นดังนั้นฉันจึงใช้คำตอบนี้เพื่อบอกว่าฉันลองทั้ง ST_MakeEnvelope และคณิตศาสตร์เปรียบเทียบการเปรียบเทียบของ "x> min_x และ x <max_x และ y> min_y และ y <max_y" .. โดยเฉลี่ย ST_MakeEnvelope ใช้เวลา 60 มิลลิวินาทีและวิชาคณิตศาสตร์เปรียบเทียบใช้เวลา 155ms กับข้อความค้นหา bbox ของฉันโดยเฉพาะ

ดังนั้นการค้นหาเชิงพื้นที่ ST_MakeEnvelope ควรเร็วกว่าการเปรียบเทียบทางคณิตศาสตร์!


1
ที่จริงแล้วถ้าคุณสร้างดัชนีที่ถูกต้อง min_x, max_x, min_y และ max_y จะเร็วขึ้นมาก ฉันมีชุดข้อมูลที่มีขนาดใหญ่มาก (มากกว่า 3 ล้านรูปหลายเหลี่ยม) และทำทั้งสองอย่างINDEXผ่าน ST_MakeEnvelope และ (ST_XMax, ST_XMin, ST_YMax, ST_YMin) และความแตกต่างนั้นเป็นประโยชน์อย่างมากต่อคณิตศาสตร์ คณิตศาสตร์เอาฉันน้อยกว่า 20s (INDEX + Query) ในขณะที่การแยกซองจดหมายใช้เวลามากกว่า 2 นาที (ฉันยอมแพ้เมื่อถึง 2
นาที 40 วินาที
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.