Fel*_*rlo 1 google-bigquery google-cloud-platform
我试图从特定位置获得2公里或更少的人数,为此我正在计算纬度和经度的距离.在一张桌子中,我只有纬度,经度,而在另一张桌子里,我有更多的田地,但也有纬度和经度.
该查询有效,运行时将处理12.3 MB.
我正在使用的查询是:
select
e.lat,
e.long,
e.searches,
count(distinct l.id)
from dataset.table1 e
join dataset.table2 l
on 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 # way to calculate distance from lats and longs
group by e.lat,
e.long,
e.searches
Run Code Online (Sandbox Code Playgroud)
但是查询没有运行,每次都需要超过15分钟,我必须取消.
可能是什么问题呢?
此查询与原始查询类似,需要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
Run Code Online (Sandbox Code Playgroud)
为了防止浮点错误,我不得不改变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
Run Code Online (Sandbox Code Playgroud)
相似的:
(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
Run Code Online (Sandbox Code Playgroud)
现在的问题是我们如何才能获得比2分钟更好的表现?让我们在JOIN中添加一些'健全'过滤器 - >同一区域中没有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
Run Code Online (Sandbox Code Playgroud)
有了这个,我们得到非常相似的结果,但在12秒而不是2分钟.
我无法优化您的确切查询,因为您的示例表没有相同的数字或行或列 - 但在进行完整的CROSS JOIN之前尝试应用这些"健全JOIN检查".
归档时间: |
|
查看次数: |
558 次 |
最近记录: |