我试图从特定位置获取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
但是查询没有运行,每次都需要超过15分钟,我必须取消。
可能是什么问题?
答案 0 :(得分:5)
此查询与原始查询类似,需要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分钟更好的表现?让我们加入一些“理智”的理智。过滤器 - &gt;在同一区域内没有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分钟。
我无法优化您的确切查询,因为您的示例表格不具有相同的数字或行数或列数 - 但尝试应用这些&#34;完整性JOIN检查&#34;在进行完整的CROSS JOIN之前。
答案 1 :(得分:2)
使用JOIN
对距离谓词进行这种强力分析并不会有很好的表现。 BigQuery团队正在考虑为地理空间分析添加更好的支持(即在ST_DWithin
谓词中使用JOIN
函数)。与此同时,放入Postgres并使用PostGIS扩展可能是您最好的选择。