在 Spanner 中查询给定半径内的地址
Querying for addresses within a given radius within Spanner
罐头上写的是什么:如何在我的 Spanner 数据库中查询在给定经度和纬度的特定半径范围内的地址?
举一个示例用例,假设我有一个餐馆数据库,我正在寻找距离我公寓十英里以内的餐馆。我目前将每个餐厅的纬度和经度存储在 Address_geolng
和 Address_geolat
字段中作为度数。为了简单的数据,我们会说我不知何故生活在空岛的热门餐厅场景的中间(例如 0,0)。
很多数据库都有内置的地理类型或某种类型的预建地理距离功能,但我在 Spanner 中都没有看到。
我一直在尝试用蛮力实现 Haversine formula 来代替其他所有方法,但老实说,我的眼睛正在穿过这里,要么我无法找到我的相关文档用例或 Spanner 缺少很多东西来帮助更简单地实现它。 (例如,它们的三角函数似乎仅以弧度为单位工作,但我没有在任何地方看到任何关于度数到弧度转换函数或引用 PI 的能力的参考……肯定有比仅仅抓住 ACOS(-1)
, 我确定....)
到目前为止我的最大努力是
COS(0) * COS(DIV(ACOS(-1),180) * Address_geolat) *
SIN(DIV(DIV(ACOS(-1),180) * (Address1_geolng - 0)), 2) * SIN(DIV(DIV(ACOS(-1),180) * (Address1_geolng - 0), 2)) AS a FROM restaurants WHERE (3959 * 2 * ATAN2(SQRT(a), SQRT(1 - a)) <= 10)
我敢肯定这甚至是不对的——我的眼睛只是在交叉,试图对所有这些进行分类。
有没有人已经为此开发了解决方案?你用的是什么?
所以我正在为此发布一个文档。你说得对,Spanner 内部没有地理空间支持,但这里有一些提示:
1) 不要在顶层使用 haversine 进行查询 select - 这意味着您必须对所有行进行完整的 table 扫描,并对每一行进行复杂的计算,因此在大型 tables
上非常慢
2) 首先计算边界矩形的角坐标,该边界矩形的边长为 20 英里,您请求的坐标位于中心。
3) 使用简单的 >/< 运算符比较经纬度和角点,查询经纬度在边界框内的地址。
由于这是一个简单的查询,您可以利用纬度和经度的二级索引来加快查询速度...(注意两极和 180° 经度!)
4) 你现在有一组有限的地址,距离你请求的位置大约 20 英里(有些稍微远一点)你现在可以通过使用半正弦或球面余弦定律计算精确距离来过滤这些地址
这种精确的距离计算/过滤可以在 SQL 中完成,但在您的应用程序中执行起来可能更容易,因为您有更多可用的数学函数并且可以使用局部变量来简化事情。由于您只有几行要处理(由于边界框上的粗过滤),这应该很快。
这是一个有用的网页,其中包含更易于阅读的公式:
https://www.movable-type.co.uk/scripts/latlong.html
罐头上写的是什么:如何在我的 Spanner 数据库中查询在给定经度和纬度的特定半径范围内的地址?
举一个示例用例,假设我有一个餐馆数据库,我正在寻找距离我公寓十英里以内的餐馆。我目前将每个餐厅的纬度和经度存储在 Address_geolng
和 Address_geolat
字段中作为度数。为了简单的数据,我们会说我不知何故生活在空岛的热门餐厅场景的中间(例如 0,0)。
很多数据库都有内置的地理类型或某种类型的预建地理距离功能,但我在 Spanner 中都没有看到。
我一直在尝试用蛮力实现 Haversine formula 来代替其他所有方法,但老实说,我的眼睛正在穿过这里,要么我无法找到我的相关文档用例或 Spanner 缺少很多东西来帮助更简单地实现它。 (例如,它们的三角函数似乎仅以弧度为单位工作,但我没有在任何地方看到任何关于度数到弧度转换函数或引用 PI 的能力的参考……肯定有比仅仅抓住 ACOS(-1)
, 我确定....)
到目前为止我的最大努力是
COS(0) * COS(DIV(ACOS(-1),180) * Address_geolat) *
SIN(DIV(DIV(ACOS(-1),180) * (Address1_geolng - 0)), 2) * SIN(DIV(DIV(ACOS(-1),180) * (Address1_geolng - 0), 2)) AS a FROM restaurants WHERE (3959 * 2 * ATAN2(SQRT(a), SQRT(1 - a)) <= 10)
我敢肯定这甚至是不对的——我的眼睛只是在交叉,试图对所有这些进行分类。
有没有人已经为此开发了解决方案?你用的是什么?
所以我正在为此发布一个文档。你说得对,Spanner 内部没有地理空间支持,但这里有一些提示:
1) 不要在顶层使用 haversine 进行查询 select - 这意味着您必须对所有行进行完整的 table 扫描,并对每一行进行复杂的计算,因此在大型 tables
上非常慢2) 首先计算边界矩形的角坐标,该边界矩形的边长为 20 英里,您请求的坐标位于中心。
3) 使用简单的 >/< 运算符比较经纬度和角点,查询经纬度在边界框内的地址。 由于这是一个简单的查询,您可以利用纬度和经度的二级索引来加快查询速度...(注意两极和 180° 经度!)
4) 你现在有一组有限的地址,距离你请求的位置大约 20 英里(有些稍微远一点)你现在可以通过使用半正弦或球面余弦定律计算精确距离来过滤这些地址
这种精确的距离计算/过滤可以在 SQL 中完成,但在您的应用程序中执行起来可能更容易,因为您有更多可用的数学函数并且可以使用局部变量来简化事情。由于您只有几行要处理(由于边界框上的粗过滤),这应该很快。
这是一个有用的网页,其中包含更易于阅读的公式: https://www.movable-type.co.uk/scripts/latlong.html