2012-06-28 38 views
0

對不起,如果這已經回答了(我確定有人會扔我的鏈接,如果有的話)。我回想起一個類似的問題,但我現在找不到它。基於距離的優化用戶數據庫搜索

所以,對於這個問題:我正在構建用戶搜索我正在開發的網站,其中一個搜索條件將基於與搜索用戶的距離。我已經有一張美國郵政編碼表及其對應的經緯度表。我還想出瞭如何確定邊界框(最大經緯度/最小緯度 - 最大長度/最小長度),以確定哪些拉鍊符合標準(我們不會擔心精確的半徑。暫時就足夠了)。我的問題 - 我應該如何構建查詢來優化速度?我應該:

  • 執行必需的數學來確定邊界框,然後查詢拉鍊表以找到那些潛在的候選人,然後用任何的那些郵政編碼搜索用戶的所有郵政編碼?

OR

  • 確定緯度/經度邊框,與用戶表連接的zip表並與用戶誰的緯度/多頭參數之間掉下返回結果?

我想第二種方法會更快,但我沒有支持證據/具體經驗,這表明它會。我知道有足夠的SQL來解決問題,但我仍然對它有所瞭解,並且在涉及到不同類型操作的相對性能時並不知情。

謝謝你的時間!

回答

2

我相信你最終的查詢應該是這樣的:

-- compute @minLat, @maxLat, @minLon, @maxLon 

SELECT users.* 
FROM users 
JOIN locations ON locations.id = users.location 
WHERE locations.latitude BETWEEN @minLat AND @maxLat 
AND locations.longitude BETWEEN @minLon AND @maxLon 

所以在這種情況下很,我不爲一切一氣呵成情況瞭解您的疑慮。查詢優化器通常比任何首先要執行的人都知道得更好。

如果你想實現一個更復雜的計算來確定郵政編碼是否在範圍內,那麼我寧願先建立一個郵政編碼列表,然後匹配居住在這些區域的用戶。

這假定計算郵政編碼是否在搜索範圍內是該操作中成本最高的部分。因此,我寧願使用盡可能最小的數據集(即僅限ZIP代碼,而不是ZIP +用戶)來運行此計算。即使在這種情況下,查詢優化器也許能夠爲您做出正確的選擇。

+0

謝謝。這個問題可能表達得很差,實際上是詢問是否執行兩個單獨的查詢(一個是獲取一個郵政編碼數組,然後是另一個郵政編碼,以查看哪個用戶與該列表中的郵編匹配),或者執行聯合(非常精確如上所示)。也許愚蠢的問題,我只是不知道連接速度是如何比較兩個單獨的查詢(沒有連接)。這是我將繼續前進的路線。感謝您花時間。 (以及其他所有人) – dgeare

+0

@dgeare如果您要使用與我建議的查詢相似的查詢,那麼您應該在'location(id,緯度,經度)'上放置一個索引。這樣,MySQL就能夠僅處理索引,並且通常可以從內存中進行處理。它往往(如果不是總是)比將拉鍊代碼列表(到應用程序層?)更快,然後用這些結果運行第二個查詢。至少你避免了兩層之間的通信(假設有多層設置,例如PHP + MySQL)。 – RandomSeed

+0

郵政編碼表目前使用郵政編碼(varchar(5))作爲PK,與users表中的外鍵字段對應。你是否建議在zip表中使用數字代理鍵會加速連接,或者當前的設置是否足夠?謝謝。 – dgeare

1

你描述可以這樣概略地說明這兩種算法:

A INNER JOIN B WHERE A satisfies condition 

(A WHERE A satisfies condition) INNER JOIN B 

前者只是一個連接(條件可能是一個連接條件或WHERE條件,但這與INNER JOIN和MySQL無關)。

後者涉及子查詢。您的描述似乎認爲子查詢是先計算的,然後是加入,但通常是not the case。內連接首先被評估,子查詢第二,這可能會給你與第一種情況相同的執行計劃。

因此,這兩種方法似乎與性能角度不同,您應該專注於選擇一種最易於閱讀和維護的方法,並在當日來臨時優化profile