這個查詢,類似於原來的一個,需要2分:
SELECT distance, COUNT(*) FROM (
SELECT
e.lat,
e.long
, 6371000*ACOS(COS(3.14159265359/180*(90-e.lat)) *COS(3.14159265359/180*(90-l.lat)) +SIN(3.14159265359/180*(90-e.lat)) *SIN(3.14159265359/180*(90-l.lat)) *COS(3.14159265359/180*(e.long-l.long))) <= 2000 distance
, e.long-l.long longlong, e.lat-l.lat latlat
FROM
`buoyant-history-159518.test_lat_long.table1` e
JOIN
`buoyant-history-159518.test_lat_long.table1` l
ON
(COS(3.14159265359/180*(90-e.lat)) *COS(3.14159265359/180*(90-l.lat)) +SIN(3.14159265359/180*(90-e.lat)) *SIN(3.14159265359/180*(90-l.lat)) *COS(3.14159265359/180*(e.long-l.long))) <= COS(2000/6371000) + 4.5E-8
)
GROUP BY distance
爲了防止浮點錯誤,我不得不在JOIN不平等變換:
6371000*ACOS(COS(3.14159265359/180*(90-e.lat)) *COS(3.14159265359/180*(90-l.lat)) +SIN(3.14159265359/180*(90-e.lat)) *SIN(3.14159265359/180*(90-l.lat)) *COS(3.14159265359/180*(e.long-l.long)))
<= 2000
的相似:
(COS(3.14159265359/180*(90-e.lat)) *COS(3.14159265359/180*(90-l.lat)) +SIN(3.14159265359/180*(90-e.lat)) *SIN(3.14159265359/180*(90-l.lat)) *COS(3.14159265359/180*(e.long-l.long))) <= COS(2000/6371000) + 4.5E-8)
<= COS(2000/6371000) + 4.5E-8
現在的問題是,我們如何才能獲得比2分鐘更好的性能?讓我們增加了加入一些「理智」過濾器 - >無2點在同一區域可以有拉特和長比0.something多之間的距離:
SELECT distance, COUNT(*) FROM (
SELECT
e.lat,
e.long
, (COS(3.14159265359/180*(90-e.lat)) *COS(3.14159265359/180*(90-l.lat)) +SIN(3.14159265359/180*(90-e.lat)) *SIN(3.14159265359/180*(90-l.lat)) *COS(3.14159265359/180*(e.long-l.long))) <= COS(2000/6371000) distance
, e.long-l.long longlong, e.lat-l.lat latlat
FROM
`buoyant-history-159518.test_lat_long.table1` e
JOIN
`buoyant-history-159518.test_lat_long.table1` l
ON
NOT (e.long=l.long AND e.lat=l.lat)
AND ABS(e.long-l.long) < 0.021 #sanity JOIN check
AND ABS(e.lat-l.lat) < 0.018 #sanity JOIN check
)
GROUP BY distance
有了這個,我們得到的結果非常相似,但在12秒而不是2分鐘。
我無法優化您的確切查詢,因爲您的示例表沒有相同的數量或行數,也沒有列數 - 但在進行完整的CROSS JOIN之前嘗試應用這些「完整性JOIN檢查」。
全表掃描可能是問題所在。您需要使用良好的索引,並且看起來您有一個非常複雜的連接。任何或所有這些事情都可能是負責任的。 – mba12
你能提供一個樣本數據集嗎?我想玩優化這個查詢,但我需要一個合適的測試牀 –
當然@FelipeHoffa,我怎麼能送你?謝謝! –