2016-03-21 143 views
2

我有一個查詢返回所有記錄,按照距固定點的距離排序,與我的MySQL 5.7數據庫中的POINT字段相比較。提高空間MySQL查詢的性能

舉個簡單的例子,讓我們說,它看起來是這樣的:

SELECT shops.*, st_distance(location, POINT(:lat, :lng)) as distanceRaw 
FROM shops 
ORDER BY distanceRaw 
LIMIT 50 

我實際的查詢也有做了幾個加入到得到結果的額外數據。

問題是,爲了按距離排序數據,它需要計算數據庫中每一條記錄的距離(目前大約有100,000條記錄)。

我無法緩存查詢,因爲它只會針對那些原始座標。

是否有限制必須計算的數據?例如附近商店的可靠粗略計算,例如lat + lng的+/- 3度?這樣它只需要處理一部分數據呢?

如果有人在這種優化方面有任何經驗,我很樂意提供一些建議,謝謝。

+0

我在[我的博客](http://mysql.rjweb.org/doc.php/latlng)上詳細討論了這個問題和一個很好的解決方案。 –

回答

1

是的,您可以在標準中使用一些簡單的近似值來過濾出那些半徑超出範圍的位置。 This great blog post題爲「爲SQL(MySQL和PostgreSQL,SQL Server)的快速的最近位置查找器」描述了這樣的優化:

記住,從我們的背景信息,本文前面, 一個度緯度的是111.045公里英寸因此,如果我們的緯度列有 索引,我們可以使用這樣的SQL子句來消除在北緯50度以內太偏北或偏南偏於 的點數 。

latitude BETWEEN latpoint - (50.0/111.045) AND latpoint + (50.0/111.045)

此WHERE子句允許的MySQL使用索引計算半正矢距離公式之前 點省略許多緯度。它允許 MySQL對緯度索引執行範圍掃描。

最後,我們可以使用一個類似但更復雜的SQL子句來消除太東或西的 點。該條款更爲複雜 ,因爲經度是距離我們移動的赤道較遠的距離 。這是公式。

longitude BETWEEN longpoint - (50.0/(111.045 * COS(RADIANS(latpoint)))) AND longpoint + (50.0/(111.045 * COS(RADIANS(latpoint))))

所以,把他們放在一起,這個查詢查找neareast 15分 是的(latpoint,longpoint)50公里的邊界框之內。

上面描述了邊界矩形的理論背景。