mysql經緯度查詢而且計算2KM範圍內附近用戶的sql查詢性能優化實例教程

 

以前很傻很天真地覺得無非就是逐個計算距離,而後比較出來就好了,而後當碰到訪問用戶不少,並且數據庫中經緯度信息不少的時候,計算量的迅速增加,能讓服務器徹底傻逼掉,仍是老前輩的經驗比咱們豐富,給了我很大的啓示。git

MySQL性能調優 – 使用更爲快速的算法進行距離計算算法

最近遇到了一個問題,經過不斷的嘗試最終將某句本來佔據近1秒的查詢優化到了0.01秒,效率提升了100倍.sql

問題是這樣的,有一張存放用戶居住地點經緯度信息的MySQL數據表,表結構能夠簡化 爲:id(int),longitude(long),latitude()long. 而業務系統中有一個功能是查找離某個用戶最近的其他數個用戶,經過代碼分析,能夠肯定原先的作法基本是這樣的:數據庫

//須要查詢的用戶的座標服務器

1 $lat=20;
2 $lon=20;//執行查詢,算出該用戶與全部其餘用戶的距離,取出最近的10個
3 $sql='select * from users_location order by ACOS(SIN(('.$lat.' * 3.1415) / 180 ) *SIN((latitude * 3.1415) / 180 ) +COS(('.$lat.' * 3.1415) / 180 ) * COS((latitude * 3.1415) / 180 ) *COS(('.$lon.' * 3.1415) / 180 - (longitude * 3.1415) / 180 ) ) * 6380 asc limit 10';

而這條sql執行的速度卻很是緩慢,用了近1秒的時間才返回結果,應該是由於order裏的子語句用了太多的數學計算公式,致使總體的運算速度降低.性能

而在實際的使用中,不太可能會發生須要計算該用戶與全部其餘用戶的距離,而後再排序的狀況,當用戶數量達到一個級別時,就能夠在一個較小的範圍裏進行搜索,而非在全部用戶中進行搜索.優化

因此對於這個例子,我增長了4個where條件,只對於經度和緯度大於或小於該用戶1度(111千米)範圍內的用戶進行距離計算,同時對數據表中的經度和緯度兩個列增長了索引來優化where語句執行時的速度..net

最終的sql語句以下code

1 $sql='select * from users_location where
2 latitude > '.$lat.'-1 and
3 latitude < '.$lat.'+1 and
4 longitude > '.$lon.'-1 and
5 longitude < '.$lon.'+1
6 order by ACOS(SIN(('.$lat.' 3.1415) / 180 ) *SIN((latitude * 3.1415) / 180 ) +COS(('.$lat.' 3.1415) / 180 ) * COS((latitude * 3.1415) / 180 ) *COS(('.$lon.'3.1415) / 180 - (longitude * 3.1415) / 180 ) ) * 6380 asc limit 10';

通過優化的sql大大提升了運行速度,在某些狀況下甚至有100倍的提高.這種從業務角度出發,縮小sql查詢範圍的方法也能夠適用在其餘地方.orm

原文地址:  http://blog.csdn.net/hustpzb/article/details/7688993

相關文章
相關標籤/搜索