它在罐头上说了什么:如何在Spanner数据库中查询在给定的经度和纬度的特定半径内的地址?
作为一个用例示例,假设我有一家餐馆数据库,并且正在寻找距离我公寓十英里范围内的餐馆。我目前在Address_geolng
和Address_geolat
字段中存储的每家餐厅的经度和纬度都以度数表示。为了获得简单的数据,我们将说我某种程度上生活在空岛(例如0,0)的热餐厅场景中间。
许多数据库具有内置的地理类型或某种类型的预建地理距离功能,但在Spanner中我都看不到任何一个。
我一直在尝试以蛮横的方式实施Haversine formula来代替所有其他方法,但是老实说,我的眼神在这里,或者我无法找到我的用例的相关文档或Spanner缺少很多东西来帮助更简单地实现这一目标。 (例如,似乎它们的trig函数仅以弧度为单位工作,但我看不到任何引用程度的弧度转换函数或PI引用的功能……总比抓取{ {1}},我确定。。。
到目前为止,我最大的努力是
ACOS(-1)
我很肯定甚至是不对的-我的目光在试图整理所有这些内容。
是否有人已经为此开发了解决方案?你用了什么?
答案 0 :(得分:2)
因此,我正在为此发布文档。您是正确的,Spanner内部没有地理空间支持,但是这里有一些提示:
1)不要在顶层select上使用Haversine进行查询-这意味着您必须对所有行进行全表扫描,并且每行都要进行复杂的计算,因此在大型表上会非常慢
2)首先计算一个边长为20英里,以您所请求的坐标为中心的矩形的角坐标。
3)使用简单的> / <运算符,将经纬度与拐角点进行比较,以查询经纬度在边界框内的地址。 由于这是一个简单的查询,因此您可以利用纬度和经度的二级索引来使查询更快...(请注意两极和180度经度!)
4)您现在拥有一组距离您请求的位置大约20英里的地址(有些距离较远),现在您可以使用正弦或余弦定律通过计算精确距离来过滤这些地址
这种精细的距离计算/过滤可以在SQL中完成,但是在您的应用程序中可能会更容易,因为您的应用程序中有更多可用的数学函数,并且可以使用局部变量来简化操作。由于您只需要处理几行(由于边界框上的粗略过滤),因此应该很快。
这是一个有用的网页,其中包含易于阅读的公式: https://www.movable-type.co.uk/scripts/latlong.html