DynamoDB 支持地理空间查询吗?
并非原生支持。DynamoDB 没有地理空间数据类型,也没有距离或边界框运算符。地理空间查询是一种建模模式:把 geohash 或 S2 单元 ID 存进键里,让邻近的点排到一起,查询覆盖你搜索区域的那些单元,然后在应用里按精确距离做二次筛选。
geohash 模式
geohash(或 S2 单元 ID,AWS 的 Geo Library for DynamoDB 用的就是它)把经纬度编码成一个字符串或数字,其_前缀_标识了一个网格单元——关键在于,邻近的点共享前缀。把它存成分区键或排序键,「我附近的点」就变成了普通的键范围查询:
- 框查询——算出覆盖某个矩形的那些单元,对每个单元执行
Query,再把结果合并。 - 半径查询——同理,覆盖一个圆的那些单元,然后在客户端按精确距离过滤。
分辨率很关键:挑一个单元尺寸,让大多数搜索只触及目标单元及其邻居。
精度如何改变查询数量
以埃菲尔铁塔为例,48.8584, 2.2945。它的 geohash 是 u09tunquc。640 米之外的特罗卡德罗在 48.8619, 2.2876,是 u09tup1c0。它们共享 u09tu,所以在精度 5 上它们处于同一个单元里。到了精度 6 就不是了。两个彼此都能看见的地标却落在不同单元里——这正是为什么一次单元查询总是必须把八个邻居连同自己的单元一起包含进来。
每多一个字符,框就收窄一次。在这个纬度上:
| 精度 | 单元尺寸 | 5 km 半径触及的单元数 |
|---|---|---|
| 4 | 25.7 × 19.6 km | 1 到 4 |
| 5 | 3.2 × 4.9 km | 10 到 12 |
| 6 | 0.81 × 0.61 km | 185 到 193 |
每一行都是一个区间,因为数量不只取决于圆有多大,还取决于它落在网格的什么位置上。单元还会向赤道方向变宽,因为在那里一度经度覆盖的地面更多。同一个精度 5 的单元在赤道上宽 4.9 km,在巴黎宽 3.2 km。
第三列才是那个设计决策。精度 6 会把一次「5 km 内的餐馆」变成大约 190 次 Query 调用。精度 4 则让它变成一两次调用,交回一个 500 km² 框里的全部内容,等你在客户端丢掉。
真正咬人的不是钱。那 190 次查询,每次返回不到 4 KB 且是最终一致的,合计 95 个读取单元,按 us-east-1 的按需费率约合每次搜索 0.000012 美元,一百万次搜索 11.88 美元。真正的成本是那些往返。请并发地发出它们并给扇出封顶,否则你搜索接口的 p99 就等于那次碰巧最慢的单元查询。
库与工具
AWS 发布过 Geo Library for Amazon DynamoDB(Java),演示了基于 S2 的这套模式,社区也有其他语言的移植(例如 Node.js 的 dynamodb-geo)。采用之前请查一下维护状态——这个模式本身简单到可以直接自己实现。
什么时候该改用搜索引擎
对于复杂的地理谓词(多边形、按距离排序、把地理和全文组合起来),请把表复制到一个专门的索引里——处理全文搜索的那套零 ETL OpenSearch 集成同样能给你一个原生支持地理空间查询的搜索引擎。
深入了解
这套模式本质上是一个排序键技巧——排序键策略指南讲了整套工具箱,表达式构建器能生成单元查询用的 begins_with/BETWEEN 条件,而 DynoTable 让你在自己真实的项目上检查这些编码后的键。
参考资料
- Geo Library for Amazon DynamoDB – Part 1: Table Structure — AWS Mobile Blog
- Implementing geohashing at scale in serverless web applications — AWS Compute Blog
- Supported data types and naming rules in Amazon DynamoDB — Amazon DynamoDB Developer Guide
最后核实于 2026-07-13,依据上方链接的 AWS 官方文档。
geohash、单元尺寸和覆盖数量于 2026-07-28 用标准 base32 geohash 编码器在纬度 48.8584 上计算得出。u09tunquc 可以用任意 geohash 工具核对。每次搜索的成本使用我们同步的定价表中 us-east-1 的按需读取费率(AWS 定价 API 发布于 2026-07-22)。