2012-05-30 166 views
0

我對MySQL和數據庫一般都很陌生,但我有一個似乎需要很長時間的查詢。我從一個位置數據庫中找到距離另一個位置5英里內的使用經緯度座標的約700,000個位置。問題是,這需要2.12秒的時間才能完成,而且我很擔心,一旦我開始獲取流量,MySQL就會阻塞。這裏是我的代碼:mysql查詢時間很慢select

SELECT *,((ACOS(SIN(44.4726 * PI()/180) * SIN(lat * PI()/180) + COS(44.4726 * PI()/  180) * COS(lat * PI()/180) * COS((-93.1785 - lon) * PI()/180)) * 180/PI()) * 60 * 1.1515) AS distance FROM locations HAVING distance<=5 ORDER BY distance ASC LIMIT 30; 

我有lat和lon字段索引但它仍然需要很長時間。這是與我要求服務器做什麼的預期?我是否可以通過添加加速

WHERE state = "$state" 

如果是的話,我會在Select?

回答

1

該查詢將seq掃描整個表格,因爲實際上沒有一個過濾器不會從計算值(距離)派生。添加一個由索引列過濾的where子句肯定有助於消除一些開銷,但只有在數據庫認爲表中有足夠的數據才能使用索引而不是表時纔有用。因此,請確保您分析它。

距離在查詢中的邏輯非常難看,但我明白了爲什麼每次從表中選擇時都不希望傳輸700k以上的行。看起來您可能正在進行空間計算,並且可能是調查空間數據類型和索引的明智之舉。

版:同樣,你對where子句的問題...

select fields [aggregate fields] 
from table 
where where clause 
group by fields 
having having clause 
+0

我已經閱讀了關於空間數據類型的經緯度和座標座標的幾篇文章,但也看到這是一個糟糕的主意,所以決定嘗試做我所做的工作。此外,我可能聽起來像我有更多的知識,這比我實際上... ...大聲笑。那麼你可以貶低where子句嗎?我只是想知道如何添加「WHERE column = $ variable」以及如何將它包含在我當前的查詢字符串中 – whatdafrak

+0

我明白了!我把一個關於狀態的索引並將我的代碼更改爲這個'....AS距離位置WHERE state ='mn'HAVING distance .....'。它將我的查詢從2.12秒變爲.262秒。我不會抱怨的。如果一個城市位於兩個州的​​邊界上,我可能會遇到問題,因爲它不會在邊界地區找到地點。但直到我能想出更長久的東西,我纔開心。謝謝您的幫助 – whatdafrak

0

你爲什麼要在查詢中進行計算?這樣的邏輯不應該在DAL中。我建議只取得你需要的列,然後在你的代碼中進行計算,這將允許你只計算沒有lat和long一次的部分(SIN(44.4726 * PI()/ 180)),例如),然後只是循環結果並在適當的時候加入經緯度。

+0

不是很瞭解。我從一個已知的經緯度位置開始。我想使用距離公式來查詢這些座標的位置表。我不知道如何做到這一點,而不查詢數據庫,並使用這些緯度和經度數對我已知的緯度和經度數。 – whatdafrak

0

我不知道怎麼這種類型的查詢的通常是這樣做的隨意無視我的建議,但假設你的應用程序什麼將輸入{lat,lon}並在每個方向(北,東,南和西)上擴展5英里。然後,您的查詢可以只選擇那些在上限和下限之間有lat和long的記錄。

您仍然必須進行距離計算,但您將排除不可能匹配的記錄,因此應該減少查詢的開銷。此外,如果你有一個長和長的索引,它應該可以使用這些。

我可能誤解了幾何,正如我所說的,我沒有這方面的經驗,但它可能是對其他建議的補充。