mysql에서 가장 가까운 이웃 검색을 구현하는 방법은 무엇입니까?


10

요컨대,

  1. 위도와 경도의 데이터 유형은 무엇입니까?
  2. 예를 들어 가장 가까운 100 개의 식당을 얻기 위해 어떤 SQL 명령을 호출해야합니까?

세부 묘사:

위도 및 경도가 각각 100k 인 비즈 레코드가 있습니다. MySQL이 실제로 point라는 데이터 유형을 지원한다는 것을 알았습니다. 대신 사용해야합니까?

MySQL이 KDTree 스토리지 시스템을 지원합니까? http://en.wikipedia.org/wiki/File:KDTree-animation.gif

위도 및 경도를 저장하기 위해 일반 부동 데이터 유형보다는 포인트 데이터 유형을 사용하는 것이 가장 좋습니까?

결국 나는 예를 들어 105,6에 가장 가까운 처음 100 개의 식당과 같은 것을 찾고 싶습니다. 내 데이터베이스에는 많은 비즈와 포인트가 있습니다. 분명히 모든 레코드와 모든 포인트에 대해 거리를 하나씩 계산하는 것은 O (n) 일 것이므로 짜증납니다.

Yelp와 같은 응용 프로그램이 데이터베이스에서 거리 정보를 효율적으로 검색하는 방법에 설명 된 더 간단한 솔루션을 알고 있으며 시작을 위해 저 자신도 구현할 것입니다. 좋은 대답입니다.

그러나 나는 그 답을 능가해야 할 작물 답변의 한 가지 크림이 있다고 생각합니까? 실제로 위도와 경도를 기준으로 위치를 저장하고 가장 가까운 물건을 찾는 것은 mysql이 특별한 디자인 패턴을 가질 것으로 예상되는 매우 일반적인 문제입니다. 그게 있습니까?

그것에 대해 더 배울 수있는 곳은 어디입니까? 감사.



dba.stackexchange.com/questions/4210/… 의 솔루션 이 최상의 솔루션입니다. MYSQL 공간이라는 것이 있습니다. 그러나 어디에서 (거리 (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

Stack Overflow의 지리 공간 거리에 대한 더 길고 심층적 인 답변이 있습니다.

그러나 여전히 위도와 경도로 결과를 제한하려고합니다.

궁극적으로 POINT 데이터 유형을 피하고 위도 / 경도로 이동합니다. 현재 두 점 사이의 거리를 결정할 방법이 없으므로 어쨌든 해당 계산을 위해 위도 / 경도를 저장해야합니다.

마지막 링크 하나 : 공간 인덱스를 사용하여 쿼리 속도를 높이는 것과 관련 하여이 SO 스레드 를 확인하는 것이 좋습니다.


[질의 4의 오류] SQL 구문에 오류가 있습니다. 오른쪽 구문 MySQL 서버 버전에 대응 근처 사용하는 설명서를 확인 '- dest.lon) * PI ()를 π / 180 / 2), 2))) (D)를 갖는 최종 도착 network_pos로부터의 거리 등의'라인 (2)에서
펠리

안녕, @dist는 밀레입니다? 감사합니다
호르헤 올라프 Erlandsen이에게

1
@OlafErlandsen 네, 그것은 마일에있어
얀 반 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은 위도이고 -122는 론입니까? 25는 미터 또는 킬로미터입니까?
Felipe

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.