2011-03-04 70 views
0

我的腳本有一點性能問題,所以我想知道有沒有人知道更好的方法來處理這個問題。使用緯度 - 經度 - 郵政編碼數據庫選擇3個最近的位置

我有一個數據庫的位置和他們的郵政編碼(編號,名稱,郵編)。在另一個表格中,我有與郵編相關的緯度和經度(經緯度,郵編)。腳本要求用戶輸入郵政編碼並返回3個最近的地點。

我現在這樣做的方式是第一:我從數據庫獲取所有位置到本地數組,然後使用mysql查詢獲取位置和每個位置的用戶郵政編碼之間的距離。

SELECT SQRT(POW((
    uc1.lat - uc2.lat 
    ), 2) + POW((
    uc1.long - uc2.long 
    ), 2)) 
FROM postcodes uc1 
LEFT JOIN postcodes uc2 ON uc1.postcode = "$postcode1" 
WHERE uc2.code = "$psotcode2" 

之後,我排序數組並顯示前3個元素。

如果位置數量很少,這可以正常工作,但是隨着它們接近數千個性能成爲問題。

任何想法?編輯: 我很清楚地球的曲率。我張貼此查詢,而不是更多的數學重之一,因此,這將是更容易理解到底發生了什麼

回答

1

創建「邊框」在WHERE子句中使用您的SQL查詢中所述in this article on Movable Type(與PHP代碼示例),則包括haversine公式在查詢中計算出實際距離,按距離ASC排序結果。

它的邊框,可以幫助你的表現,因爲這意味着你只能做你的數據

+0

聽起來很有希望,我會試試看。有關如何選擇邊界框的建議,以確保其內部至少有3個位置?或者我應該嘗試一個小的,如果少於三個地點返回嘗試較大的一個,然後再大一點? – Ivan 2011-03-04 15:41:37

+0

我會傾向於變小,然後增加邊界框...從第一個結果存儲返回值,然後對於後續查詢,可以使用雙邊界框(包含一個新的更寬的邊界框,但與先前的邊界框忽略這個時間)......這樣,您不會重新計算以前查詢返回的相同結果。它使代碼稍微複雜一點,如果能夠在單個查詢中獲得完整結果,它的效果會更好,但應該比完整的數據庫搜索快得多。 – 2011-03-04 15:49:24

0

首先你的距離計算不考慮地球

你應該看看使用的東西的曲率這樣

SELECT id, place_name, 
((ACOS(SIN($lat * PI()/180) * SIN(`lat` * PI()/180) + COS($lat * PI()/180) * COS(`lat` * PI()/180) * COS(($lon – `lon`) * PI()/180)) * 180/PI()) * 60 * 1.1515) AS distance 
FROM places 
ORDER BY distance ASC 
+0

感謝您的一小部分昂貴的距離計算,但我在我的項目中使用不同的查詢,我只是認爲數學在這裏並不重要。並且只會提取可讀性。問題是關於表現,而不是關於準確性。 – Ivan 2011-03-04 15:02:17