DynamoDB中GSI与LSI对比:LSI适用场景及实例问询
什么时候该用本地二级索引(LSI)而非全局二级索引(GSI)?
我完全懂你的困惑——刚接触DynamoDB时,总觉得GSI能覆盖全表、灵活性拉满,LSI好像没什么用武之地。咱们先解决你提到的那个例子,再聊聊LSI真正不可替代的场景。
先聊你问的GenreAlbumTitle索引
假设原表的主键是Artist(分区键)+ SongTitle(排序键),那这个索引的定位很关键:
- 如果你的查询是针对某个特定Artist,想按
Genre→AlbumTitle排序查看他的歌曲,那必须用LSI。因为LSI的分区键和主表完全一致(也就是Artist),它只会为每个Artist分区内的数据建立排序索引,让你能在单个分区内快速做多维度排序查询。 - 但如果你的查询是跨所有Artist,比如找所有
Genre为"Rock"的歌曲,那这时候才需要GSI(把Genre作为GSI的分区键)。
LSI真正必要的场景
LSI的核心价值在于和主表分区键绑定,这带来了几个GSI无法替代的优势:
1. 强一致性的分区内查询
GSI是最终一致的,而LSI和主表同分区,支持强一致性读取。比如:
- 你有一个订单表,分区键是
UserID,主排序键是OrderTime。用户刚下完单,你需要立刻查询该用户金额最高的订单——这时候用LSI(把OrderAmount作为排序键)能保证拿到最新数据,GSI可能因为同步延迟返回旧数据。
2. 同分区内的多维度排序/范围查询组合
如果你的业务逻辑需要针对单个分区内的数据做复杂排序,LSI是最优解:
- 比如社交媒体帖子表,分区键是
UserID,主排序键是PostTime。你想给每个用户的帖子按「点赞数+发布时间」排序,或者「评论数+发布时间」排序——LSI可以把这些属性组合作为排序键,让你快速查询某个用户点赞Top10的帖子,或者近30天评论最多的内容。 - 这种场景下,就算你把
UserID作为GSI的分区键,GSI的写成本更高(每写主表一行,额外写一行GSI),而且LSI和主表存储在一起,查询性能更优。
3. 更低的成本与无额外写延迟
LSI是和主表数据存储在一起的,写入主表时自动同步索引,不需要额外的写请求费用。而GSI每写入主表一行,就会产生额外的GSI写请求,长期下来成本差异很明显。如果你的查询都是基于主表分区键的,只是需要不同的排序维度,LSI性价比更高。
4. 默认投影所有属性
LSI默认会投影主表的所有属性到索引中,查询时直接从索引就能获取完整数据,不需要额外回表。而GSI默认只投影主键属性,如果你需要其他属性,得手动配置投影,不仅麻烦,还可能增加存储成本。
最后再回应你的疑问
你说“所需的索引似乎都需要覆盖整张表”,那可能是还没遇到按分区聚合查询的场景。比如:
- 不是查所有用户的高金额订单,而是查某个特定用户的;
- 不是查全平台的热门帖子,而是查某个创作者的热门内容;
- 不是查所有商家的最新订单,而是查某个商家的待处理订单。
这些场景下,LSI的针对性更强,性能、成本、一致性都比GSI更合适。
内容的提问来源于stack exchange,提问作者Bluetoba
相关产品推荐
相关产品推荐

