วิธีที่ดีที่สุดใช้การค้นหาเพื่อนบ้านที่ใกล้ที่สุดใน mysql


10

ดังนั้นในระยะสั้น

  1. ข้อมูลละติจูดและลองจิจูดควรเป็นประเภทใด
  2. ฉันควรเรียกใช้คำสั่ง SQL เพื่อรับร้านอาหารที่ใกล้ที่สุด 100 แห่งแรกหรือไม่

รายละเอียด:

ฉันมีบันทึกขนาด 100k biz แต่ละรายการที่มี lattitude และลองจิจูด ฉันเห็นว่า MySQL สนับสนุนชนิดข้อมูลที่เรียกว่า point จริงๆ ฉันควรใช้สิ่งนี้แทนหรือไม่

MySQL รองรับระบบจัดเก็บ KDTree หรือไม่http://en.wikipedia.org/wiki/File:KDTree-animation.gif

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

ในที่สุดฉันต้องการค้นหาสิ่งต่าง ๆ เช่นร้านอาหาร 100 แห่งแรกที่อยู่ใกล้กับจุด 105,6 และฐานข้อมูลของฉันมีจำนวนมากและคะแนน เห็นได้ชัดว่าการคำนวณระยะทางทีละหนึ่งสำหรับทุกระเบียนและทุกจุดจะเป็น O (n) และด้วยเหตุนี้

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

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

ฉันจะเรียนรู้เพิ่มเติมเกี่ยวกับมันได้ที่ไหน ขอบคุณ


คุณเคยเห็นคำถาม SO นี้หรือไม่?
แจ็คบอกว่าลอง topanswers.xyz

ดูเหมือนว่าโซลูชันในที่นี่dba.stackexchange.com/questions/4210/…เป็นทางออกที่ดีที่สุด ฉันหมายความว่ามีสิ่งนี้เรียกว่า MYSQL spatial อย่างไรก็ตามคุณไม่สามารถดึงสิ่งต่าง ๆ ออกมาได้เช่นที่ไหน (ระยะทาง (x) <20) ยังไม่ได้ใช้งาน
user4951

คำตอบ:


11

เท่าที่รูปแบบการออกแบบคำถาม Yelpเป็นสิ่งมาตรฐานสวย

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

จากสไลด์ของพวกเขา

set @orig_lat=122.4058; set @orig_lon=37.7907;
set @dist=10;

SELECT *, 3956 * 2 * ASIN(SQRT(
POWER(SIN((@orig_lat - abs(dest.lat)) * pi()/180 / 2), 2) +  COS(@orig_lat * pi()/180 ) * COS(abs(dest.lat) * pi()/180) *  POWER(SIN((@orig_lon  dest.lon) * pi()/180 / 2), 2) )) as  distance
FROM hotels dest 
having distance < @dist
ORDER BY distance limit 10

มีอีกต่อไปคำตอบเพิ่มเติมในเชิงลึกเกี่ยวกับระยะทางในเชิงพื้นที่เป็นกองมากเกิน

แต่คุณยังต้องการ จำกัด ผลลัพธ์ตามละติจูดและลองจิจูด

ในที่สุดฉันจะหลีกเลี่ยงประเภทข้อมูล POINT และไปกับละติจูด / ลองจิจูด ขณะนี้ยังไม่มีวิธีกำหนดระยะห่างระหว่างจุดสองจุดดังนั้นคุณจะต้องเก็บละติจูด / ลองจิจูดสำหรับการคำนวณต่อไป

ลิงก์สุดท้ายหนึ่งลิงก์: คุณอาจต้องการตรวจสอบเธรด SO นี้เพื่อเร่งการสืบค้นโดยใช้ดัชนีเชิงพื้นที่


[ข้อผิดพลาดในแบบสอบถาม 4] คุณมีข้อผิดพลาดในไวยากรณ์ SQL ของคุณ ตรวจสอบคู่มือที่สอดคล้องกับรุ่นเซิร์ฟเวอร์ MySQL ของคุณเพื่อหาไวยากรณ์ที่ถูกต้องที่จะใช้ใกล้ '- dest.lon) * pi () / 180/2), 2))) เป็นระยะทางจาก network_pos ปลายทางมี d' ที่บรรทัด 2
Felipe

สวัสดี @dist อยู่ใน milles? ขอบคุณ
Jorge Olaf Erlandsen

1
@OlafErlandsen ใช่มันอยู่ในระยะไมล์
Jan van der Vegt

4

ประเภทข้อมูลจุดตกลง; คุณสามารถเรียก X (coord) / Y (coord) เพื่อรับค่า Lat / Lon

ตัวอย่างเช่น:

SELECT id, 
(3959 
    * acos(
        cos(radians(37)) 
        * cos(radians(Y(coord)))
        * cos(radians(X(coord)) - radians(-122)) 
        + sin(radians(37))
        * sin(radians(Y(coord)))
      )
) AS distance 
FROM markers HAVING distance < 25 
ORDER BY distance LIMIT 20;

37 คือ lat และ -122 เป็นอะไรเปล่า และ 25 คือเมตรหรือกม.
เฟลิเป้

1

ค้นหาร้านอาหาร 100 แห่งที่อยู่ใกล้กับพิกัด: ดูรหัสที่มีประสิทธิภาพใน http://mysql.rjweb.org/doc.php/latlng มันมีฟังก์ชั่นที่จัดเก็บไว้สำหรับการคำนวณระยะทาง "cirle" ที่ยอดเยี่ยม

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