PolarDB-X 全局二级索引

背景

索引是数据库的基础组件,早在1970年代,SystemR 就已经通过增加索引来支持多维度查询。单机数据库中,索引主要按照用途和使用的数据结构分为 BTree 索引、Hash 索引、全文索引、空间索引等。通常,每张表中包含一个主键索引(Primary Index),主键索引以外的索引,统称为二级索引(Secondary Index)。

采用存储计算分离和 shared-nothing 架构的分布式数据库具备良好的水平扩展能力,通过数据分区和无状态的计算节点,允许计算和存储独立扩缩容,大量分布式数据库都采用这种架构(Spanner, CockroachDB, YugabyteDB 等)。

全局索引解决什么问题?

shared-nothing 架构引入了 分区 的概念,数据需要按照固定的 分区键 进行切分,这导致包含分区键的查询可以快速定位到一个具体分区,而其它查询需要全分区扫描。这个情况类似单机数据库中按照主键进行查询可以快速定位到数据所在的page,而按照非主键查询需要全表扫描。

与单机数据库不同的是,全分区扫描对于分布式数据库,除了会增加慢查询数量降低系统吞吐,还可能导致系统丧失线性扩展能力。参考下图的例子

扩容前:两个存储节点(Data Node, DN),两个数据分区,假设单个 DN 能承载的物理 QPS 为3,整体物理 QPS 为6,每个查询都是全分区扫描,逻辑 QPS: 6/2=3
扩容后:三个存储节点,三个数据分区,整体物理 QPS 为9,每个查询都是全分区扫描,逻辑 QPS: 9/3=3。机器成本上升50%,查询性能没有任何提升!

单机数据库使用二级索引来避免全表扫描,具体来说,二级索引选择非主键列作为 key,value 部分保存主键的值(也可能是到行记录的引用,具体实现不影响解题思路)。使用二级索引的查询过程变为,首先根据二级索引的索引列定位到page,读取主键的取值,然后返回主键索引查询整行记录(这一步称为回表)。本质上,二级索引通过冗余一份数据的方式,避免了全表扫描,属于系统优化的标准思路“空间换时间”

分布式数据库要消除全分区扫描,也可以采用类似的思路,冗余一份索引数据,索引采用与主表不同的分区键。查询时首先根据索引的分区键定位到一个分区,然后从分区中查到主表的分区键和主键,回表得到完整数据,整个只需要扫描固定数量的分区(比如对于点查,至多扫描两个分区)。

这种与主表分区维度不同的索引,我们称之为全局二级索引(Global Secondary Index, GSI, 也经常简称为全局索引),对应的与主表分区维度相同的索引,称为局部索引(Local Secondary Index,LSI)

为什么一定需要全局索引?

前面一直在说,全分区扫描会导致系统不可扩展,那么如果用户能够严格保证所有 SQL 都包含分区键,是不是就不需要全局索引了?

是的,这种情况确实不需要,但现实情况的复杂性决定了这是小概率事件,更常见的场景是:

● 用户表需要支持用户按照手机号和用户ID登录,分区键选哪个?
● 电商系统,需要按照买家ID和卖家ID查询订单,订单表分区键怎么选?
● 现有业务代码是外包公司写的,大范围修改SQL不现实,怎么办?

更多场景分析可以参考 TPCC与透明分布式,结论:要想提供与单机数据库相似的“透明分布式”使用体验,必须支持全局索引。

用户想要怎样的全局索引使用体验?

单机数据库中索引是非常常用的组件,用户接受度很高,全局索引如果能够做到与单机数据库索引相似的使用体验,就可以称得上是“透明”的索引使用体验。以下从用户使用视角出发,列举四个影响索引使用体验的关键特性

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值