ฉันจะค้นหาสถานที่สำคัญทั้งหมดภายในขอบเขตของสถานที่สำคัญได้อย่างมีประสิทธิภาพได้อย่างไร


14

ฉันกำลังพยายามเริ่มต้นด้วยโครงการค้นหาทางภูมิศาสตร์ที่จะพบสถานที่สำคัญทั้งหมดในระยะ 10 กม. / ไมล์ (ไม่สำคัญสำหรับเรื่องนี้) ของจุดสังเกตเฉพาะ

ตัวอย่างเช่นสมมุติว่าฉันมีฐานข้อมูลของสถานที่สำคัญ 1,000,000 แห่ง เพื่อหาจุดสังเกตทั้งหมดในช่วง 10 ไมล์ของจุดสังเกตที่มีพิกัดบางอย่างฉันจะต้องคำนวณระยะทางระหว่างจุดสังเกตจากการค้นหาของฉันกับจุดสังเกต 1,000,000 จุด

มีวิธีที่ดีกว่าในการทำเช่นนั้น?

ทางเลือกที่ฉันคิดคือจัดหมวดหมู่สถานที่สำคัญเช่นประเทศภูมิภาคเมืองย่านธุรกิจประวัติศาสตร์ ฯลฯ ในลักษณะที่ธุรกิจสามารถเป็นส่วนหนึ่งของพื้นที่ใกล้เคียงหรือเมือง เมืองเป็นส่วนหนึ่งของภูมิภาคประเทศ ฯลฯ สิ่งนี้สามารถทำให้รายการการคำนวณแคบลง แต่มันก็ดูเหมือนว่าจะมีหลายงานที่ต้องทำเพื่อให้การค้นหารวดเร็วและแม่นยำ

Google Maps API ช่วยได้ไหม


5
คุณอาจกำจัดจำนวนมากได้ง่ายๆโดยการคำนวณระยะทางแบบแมนฮัตตันอย่างรวดเร็วจากนั้นทำการกรองแบบที่สองหลังจากนั้นเพื่อแยกจุดสังเกตที่อยู่ในพื้นที่ 10 กม. แต่อยู่นอกรัศมี 10 กม.
Neil

3
คุณใช้เทคโนโลยีฐานข้อมูลใดอยู่ คำตอบคือไม่เชื่อเรื่องฐานข้อมูล
jpmc26

1
@Neil ในฐานะบัตรผ่านที่สองคุณสามารถใส่เครื่องหมายบอกตำแหน่งใด ๆ ที่ x และ y ตกอยู่ในระยะทาง 7 กม. โดยไม่คำนวณระยะทางจริง
JimmyJames

คำตอบ:


10

ตั้งแต่ SQL Server 2008 มีชนิดข้อมูลทางภูมิศาสตร์ที่เก็บตำแหน่งที่ตั้ง (คู่ lat / lon) และทำให้คุณเขียนแบบสอบถามที่เกี่ยวข้องกับตำแหน่งได้ง่าย

มีคำตอบ StackOverflow ที่มีอยู่ซึ่งกล่าวถึงสิ่งนี้ในเชิงลึก

ข้อความค้นหาพื้นฐานเพื่อค้นหา 7 รายการที่ใกล้ที่สุด :

USE AdventureWorks2012  
GO  
DECLARE @g geography = 'POINT(-121.626 47.8315)';  
SELECT TOP(7) SpatialLocation.ToString(), City FROM Person.Address  
WHERE SpatialLocation.STDistance(@g) IS NOT NULL  
ORDER BY SpatialLocation.STDistance(@g);  

ข้อความค้นหาพื้นฐานเพื่อค้นหาทุกสิ่งภายใน 100m (คำตอบที่สองสำหรับคำถาม)

-- Get the center point
DECLARE @g geography
SELECT @g = geo FROM yourTable WHERE PointId = something

-- Get the results, radius 100m
SELECT * FROM yourTable WHERE @g.STDistance(geo) <= 100

11
@KonradRudolph: เป็นกรณีของคอลัมน์ SQL ใด ๆ ที่ใช้สำหรับการสอบถามในตารางที่มี rowcount ขนาดใหญ่ คุณถูกต้อง แต่ความคิดเห็นนั้นจะมีผลกับการสืบค้น SQL ใด ๆ ที่โพสต์เป็นคำตอบ
Flater

2
คุณอ่าน "MS SQL Server" จากคำถามนี้ที่ไหน
Doc Brown

3
@ Flater ฉันยอมรับว่าปกติแล้วมันจะชัดเจนและซ้ำซ้อน แต่ถ้อยคำของ OP ดูเหมือนจะแนะนำว่าพวกเขาไม่รู้กลไกดังกล่าว
Konrad Rudolph

2
@ jpmc26: คุณตกใจที่ฉันระบุตัวเลือกที่ถูกต้องและไม่ได้รวมตัวเลือกอื่น ๆ อะไร? หากคุณรู้สึกว่าเกี่ยวข้องกับการเพิ่ม PostGIS ให้เพิ่มคำตอบด้วยตัวคุณเอง (ซึ่งคุณทำ) และอย่าหันไปวิพากษ์วิจารณ์ผู้อื่นเนื่องจากไม่มีความคิดเดียวกับคุณ
Flater

3
คำตอบของคุณปรากฏแก่ฉันโดยทั่วไปเป็นเพียงระดับเสียง MS SQL ความคิดเห็นของคุณแนะนำให้พวกเขาสลับฐานข้อมูลไปยังบางสิ่งที่อาจมีค่าใช้จ่าย 10 หมื่นดอลลาร์โดยที่ไม่ต้องสอบถามว่าสถานการณ์ของพวกเขาทำให้ปรากฏตัวขึ้นอย่างไร มันไม่ได้อธิบายถึงวิธีที่ OP สามารถใช้คิวรีของพวกเขาหรือพูดคุยเกี่ยวกับความจริงที่ว่าการทำเช่นนั้นและการใช้ดัชนีอวกาศนั้นไม่ตรงไปตรงมาใน MS SQL เหมือนกับในฐานข้อมูลอื่น ๆ และไม่พูดถึงแนวคิดพื้นฐานใด ๆ มันเป็นคำตอบที่ไม่ดีโดยไม่คำนึงว่ามันจะ "ถูกต้อง" นั่นเป็นสาเหตุที่ทำให้ฉันรำคาญใจ
jpmc26

29

ใช้ฐานข้อมูลที่รองรับการสืบค้นGIS (ระบบข้อมูลทางภูมิศาสตร์) ฐานข้อมูลส่วนใหญ่รองรับเอาท์ไรท์นี้หรือมีส่วนขยาย แต่รายละเอียดจะเฉพาะฐานข้อมูล (ในคำตอบของพวกเขา Flater จะแสดงไวยากรณ์สำหรับเซิร์ฟเวอร์ SQL)

หากคุณจำเป็นต้องใช้คำสั่งดังกล่าวภายในแอพลิเคชันของคุณคุณสามารถใช้โครงสร้างข้อมูลที่ช่วยให้คำสั่งเชิงพื้นที่เช่นKD ต้นไม้ นี่เป็นเหมือนแผนภูมิการค้นหาแบบไบนารียกเว้นว่าแต่ละระดับของพาร์ติชันแผนผังบนมิติพิกัดที่แตกต่างกัน สิ่งนี้ช่วยให้คุณสามารถ จำกัด การค้นหาเฉพาะกลุ่มที่มีความเป็นไปได้น้อยกว่า ได้อย่างมีประสิทธิภาพคุณแปลการค้นหาของคุณ "รัศมี 10km" เป็นขอบเขตสำหรับแต่ละมิติประสานงานและกระชับขอบเขตในขณะที่คุณ recurse ในต้นไม้



8
PostGISเป็นตัวเลือกฟรีชั้นนำ มันสนับสนุนมากขึ้นกว่า SQL Server เป็นประเภท GIS ขั้นพื้นฐานมากและฟังก์ชั่น แต่นี่เป็นฟังก์ชั่นพื้นฐาน
jpmc26

@ มอนสเตอร์ฉันพบว่าความคิดเห็นของ jpmc26 เป็นส่วนเสริมที่ดีและไม่มากเท่ากับการวิจารณ์ตัวอย่างของคุณ "ถ้าคุณต้องการเริ่มต้นจากศูนย์คุณไม่จำเป็นต้องจ่ายค่า DB ที่ได้รับอนุญาตซึ่งฟรีและโอเพนซอร์ซนี้ก็ทำได้ดีเช่นกัน"
mgarciaisaia

11

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

สิ่งที่คุณต้องการค้นหาคือข้อความค้นหา "ภายใน" (ข้อความค้นหารูปทรงภายในระยะทางที่กำหนดของรูปทรงเรขาคณิตอื่น ๆ ) สิ่งเหล่านี้เป็นมาตรฐานและเป็นปัญหาที่แก้ไขได้มากและเป็นไปได้ในฐานข้อมูลทั้งหมดข้างต้น (และสร้างขึ้นในหลาย ๆ ):

  • PostGIS: ST_DWithin
  • SQL Server: STDistance(ไม่ชัดเจนว่าดัชนีรองรับการใช้งานฟังก์ชั่นเวอร์ชั่น 3 มิติทางภูมิศาสตร์)
  • Oracle: SDO_WITHIN_DISTANCE(นี่ไม่ได้พูดอย่างชัดเจนว่ามันจะทริกเกอร์การใช้ดัชนีฉันต้องตรวจสอบแผนคิวรีอีกครั้งคุณอาจต้องใช้การSDO_FILTERเพื่อให้มันใช้ดัชนี
  • MySQL: ยังคงหาคำตอบอยู่

วิธีแก้ปัญหาสำหรับการเรียกใช้ดัชนี

ในกรณีที่แย่ที่สุดที่คุณมีปัญหาในการทำให้ระบบใช้ดัชนีเชิงพื้นที่กับข้อความค้นหาเหล่านี้คุณสามารถเพิ่มตัวกรองเพิ่มเติมได้ คุณจะสร้างกล่องสี่เหลี่ยมจัตุรัสที่มีด้านยาว 2 * (ระยะการค้นหา) ที่กึ่งกลางที่จุดค้นหาของคุณและเปรียบเทียบกล่องขอบสี่เหลี่ยมของรูปทรงเรขาคณิตเทียบกับก่อนที่จะตรวจสอบระยะทางจริง นั่นคือสิ่งที่ PostGIS ' ST_DWithinด้านบนทำภายใน


ระยะทางใน GIS

ในขณะที่ดัชนีเชิงพื้นที่นั้นยอดเยี่ยมและเป็นทางออกที่ถูกต้องสำหรับปัญหาของคุณการคำนวณระยะทางอาจมีความซับซ้อนทางตรรกะ โดยเฉพาะอย่างยิ่งคุณต้องกังวลเกี่ยวกับสิ่งที่การฉาย (โดยทั่วไปพารามิเตอร์ทั้งหมดสำหรับระบบพิกัด) ข้อมูลของคุณจะถูกเก็บไว้ในประมาณการ 2D ส่วนใหญ่ (สิ่งอื่นที่นอกเหนือจากระบบพิกัดเชิงมุมเช่นประมาณการละติจูด / ลองจิจูดยาว) ต่างๆ ยกตัวอย่างเช่นเว็บถ่ายภาพ Mercator (หนึ่งใช้โดย Google, Bing และทุกผู้ให้บริการแผนที่ฐานที่สำคัญอื่น ๆ ) ขยายพื้นที่และระยะทางมากขึ้นเป็นสถานที่ที่ได้รับเพิ่มเติมจากเส้นศูนย์สูตร ฉันอาจจะผิดเพราะฉันไม่ได้รับการศึกษาอย่างเป็นทางการใน GIS แต่สิ่งที่ดีที่สุดที่ฉันเคยเห็นสำหรับการคาดการณ์ 2 มิติคือบางคนที่เจาะจงว่าสัญญาระยะทางที่ถูกต้องจากจุดเดียวที่คงที่ในโลกทั้งใบ (ไม่มันไม่สามารถใช้การฉายภาพที่แตกต่างกันสำหรับทุกข้อความค้นหาซึ่งจะทำให้ดัชนีของคุณไร้ประโยชน์)

บรรทัดล่างคือคุณต้องแน่ใจว่าคณิตศาสตร์ของคุณถูกต้อง วิธีที่ง่ายที่สุดในการทำเช่นนั้นจากมุมมองการพัฒนาคือการใช้การประมาณมุม (ซึ่งมักเรียกกันว่า "ทางภูมิศาสตร์") และฟังก์ชั่นที่สนับสนุนการทำคณิตศาสตร์โดยใช้แบบจำลองทรงกลม แต่การคำนวณเหล่านี้มีราคาแพงกว่าคู่ 2D และบางฐานข้อมูลอาจไม่สนับสนุนการจัดทำดัชนี หากคุณสามารถใช้ประสิทธิภาพที่ยอมรับได้นั่นอาจเป็นหนทางไป ตัวเลือกทั่วไปอีกประการหนึ่งคือการคาดการณ์ระดับภูมิภาค (เช่นโซน UTM) ที่ได้รับทั้งระยะทางและพื้นที่ที่ใกล้เคียงกับการแก้ไขหากข้อมูลของคุณถูก จำกัด อยู่ในส่วนใดส่วนหนึ่งของโลก สิ่งที่ดีที่สุดสำหรับแอปของคุณจะขึ้นอยู่กับข้อกำหนดเฉพาะของคุณ

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


3

ฉันจะยอมรับว่าถ้าเป็นไปได้โดยใช้การสนับสนุนเฉพาะในฐานข้อมูลจะเป็นวิธีที่เหมาะสมที่สุดในการทำเช่นนี้

อย่างไรก็ตามถ้าฉันต้องทำสิ่งนี้บนฐานข้อมูลโดยไม่มีการสนับสนุนที่เฉพาะเจาะจงฉันจะเริ่มต้นด้วยการค้นหาสี่เหลี่ยมที่ล้อมรอบ circule เช่น (y> (y1 - rad)) และ (y <(y1 + rad)) และ (x> ( x1 - rad)) AND (x <(x1 + rad)) สมมติว่าคะแนนของคุณมีอย่างสม่ำเสมอแม้แต่การสอบถามการแจกแจงสำหรับสแควร์จะทำให้คุณได้รับการแข่งขันที่แท้จริงรวมทั้งการแข่งขันที่ผิดพลาดเป็นพิเศษอีกประมาณ 30% จากนั้นคุณสามารถคัดออกการแข่งขันเท็จ


แต่ถ้าไม่มีดัชนีเชิงพื้นที่ที่เหมาะสมเคียวรีดังกล่าวจะสแกนฐานข้อมูลทั้งหมดที่แย่ที่สุดในรายการทั้งหมดในช่วงละติจูดหรือลองจิจูดที่กำหนดขึ้นอยู่กับดัชนีของคุณนั่นคือ "วงดนตรี" แทนที่จะเป็นสี่เหลี่ยมจัตุรัส หากคุณไม่ต้องการที่จะฆ่าประสิทธิภาพให้ใช้ฐานข้อมูลที่สนับสนุนดัชนีเชิงพื้นที่!
jcaron

@jcaron ผมเชื่อว่าคำนี้อาจจะเหมาะสมกับดัชนี B ต้นไม้สามัญและx y(อาจจะรวมกันหรือแยกจากกันฉันจะ
เล่าให้ฟัง

@ jpmc26 ไม่เป็นไปไม่ได้ ลองคิดดูคุณจะเห็น
jcaron

@jcaron บางทีมันอาจจะดีกว่าถ้าคุณไม่ได้ปิดบังความลับเกี่ยวกับบางสิ่งที่ไม่ชัดเจนตรงไปตรงมา B-trees สามารถใช้สำหรับการBETWEENสืบค้น ฉันไม่เห็นว่าทำไมกรณีที่เลวร้ายที่สุดที่คุณไม่มีดัชนี 2 ตัวจากนั้นผลลัพธ์ที่กรองจากแต่ละดัชนีจะรวมเข้าด้วยกัน (นั่นคือสิ่งที่ RDBMS ทำภายในเมื่อพวกเขาคิดว่ามันคุ้มค่ากับการใช้ดัชนีหลาย ๆ อัน) ถ้าดัชนีที่รวมกันทำงานได้ก็ควรกรองมิติหนึ่งทั้งหมดในระดับแรกและค่อนข้างแคบลงอย่างรวดเร็วในระดับที่สอง
jpmc26

2
@jcaron จริงคุณสามารถใช้ดัชนีสำหรับสิ่งที่ต้องการ y between -68 and -69 and x between 10 and 11แต่ของดัชนีเชิงพื้นที่แน่นอนจะได้งานที่ดีกว่าสำหรับงานที่
Juan Carlos Oropeza
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.