龙空技术网

分布式系统二级索引的设计

小码匠科技 164

前言:

今天朋友们对“apachephoenix”大致比较看重,各位老铁们都需要了解一些“apachephoenix”的相关内容。那么小编在网上收集了一些有关“apachephoenix””的相关知识,希望我们能喜欢,我们快快来学习一下吧!

1 什么是索引

索引是提升查询速度的一种数据结构,目前索引的分类,主键索引(Primary Index)以外的索引,统称为二级索引(Secondary Index)。二级索引通过冗余一份数据的方式,避免了全表扫描,属于系统优化的标准思路“空间换时间”。

目前通用分布式索引的方案有:

外接索引:Apache Phoenix(HBase)全局二级索引:PolarDB-X、TiDB、CockroachDB局部二级索引:LRE、Cassandra, MongoDB、OceanBase、PolarDB-X

全局(global)索引和局部(local)索引的区别是什么?其实最主要的区别是局部索引是分区级的,即索引表的分区一一对应主表的分区,全局索引是表级的,即全局索引的分区与主表的分区没有对应关系。换句话说,local指的是分区级的local,global指的是表级的global。例如,t1表有两个hash分区,如果建局部索引i1,则i1一定有两个分区,并且i1的第一个分区是对t1的第一个分区的索引,i1的第二个分区是对t1的第二个分区的索引。如果对t1建全局索引i2,则i2可以有一个分区,也可以由多个分区,不与主表一一对应。因为局部索引跟主表的分区是一一对应的,所以在ob中,我们将局部索引的分区与主表的分区紧密绑定在一起,这样主表分区和索引表分区的location信息是一致的(一定在一台机器上),从而避免跨机的分布式事务。

因此,上述选择索引构建路径时,对全局索引有个优化,如果全局索引的主表和索引表都是非分区表,那这种全局索引可以走局部索引的构建流程。

索引性能对比测试:

分布式数据库实现的全局索引中,即使只有1个索引,性能也都会下跌到30%以下,在8个索引的情况下,性能基本都会跌倒10%以下。MySQL这种单机数据库,8个索引的情况下,性能依然保持在85%以上分布式事务跟单机事务相比,在成本(或者说性能)上依然存在不可逾越的鸿沟,这个差距至少在3倍以上。使用全局索引替代单机数据库索引会带来很高的成本,在成本敏感型的场景中,需要适当的使用本地索引来降低使用成本。支持分布式事务下的本地索引不考虑数据和索引的亲和性,性能几乎与全局索引差不多。2 索引的分类2.1 全局二级索引(Global Secondary Index,GSI)

索引的创建:全局二级索引中的数据按照指定的拆分方式分布在各个存储节点上。每个GSI对应一张分布式索引表,和其他分布式表一样,按照指定的分区规则水平拆分为多张物理表。通过全局二级索引,用户能够按需增加拆分维度、提供全局唯一约束等。

数据写入的一致性

数据写入时,由于主表和 GSI 的数据可能位于不同分区,需要分布式事务保证原子提交,同时由于写入存在并发,还需要处理写写冲突。对于没有全局索引的表,可以将 DML 语句路由到数据所在的分区,由 DN 完成并发控制,但对于包含 GSI 的表,更新数据时需要首先读取并锁定要变更的数据,然后按照主键更新主表和索引,这种先读后写的方法称为逻辑多写。

索引创建的数据一致性

保证数据一致性的第二个方面,是在索引创建过程当中保证数据一致。比如,下面左边这幅图,分布式场景下,多个节点对元数据的感知可能存在时间差。参考图中的情况,一个节点已知存在索引,所以它对索引进行了插入,同时写入主表和索引表。另一个节点并不知道索引的存在,所以它只对主表上的内容进行删除,没有删除索引表上的内容,这就导致索引表上多了一条数据。PolarDB-X 为了解决这问题,参考 Google F1 的方案,通过引入多个相互兼容的阶段,来保证元数据的过渡是平滑的。

索引扫描的数据一致性

数据写入过程中由于存在并发,需要处理写写冲突,同样的,数据读取过程中由于存在并发读写,还需要处理读写冲突。现代数据库基本都通过 MVCC 来解决读写冲突,查询开始前从发号器获取一个版本号,通过版本号来判断数据行的最新版本是否对当前事务可见,使得读取到的数据满足指定隔离级别。PolarDB-X 支持基于 TSO 的 MVCC 实现,能够保证回表过程中索引表和主表读到相同的快照,MVCC 实现参考这篇文章。

全局二级索引还支持以下特性:

支持选择覆盖列,减少回表操作开销。在线表结构变更,添加GSI不锁主表。支持通过HINT指定索引,自动判断是否需要回表。

全局二级索引的好处:索引和数据分开存储,基于索引表的查询只需要扫描索引表。客户端的查询不需要向每个数据服务节点发送查询请求在合并结果。缺点是依赖分布式事务保证数据和索引的一致性,对性能有比较大的影响。

2.1.1 PolarDB-X

PolarDB-X二级索引推荐的使用流程:

step 1 把表结构和数据从mysql导进来(这时候其实全部索引都是全局的)step 2 发布应用,调整不兼容的shemastep 3 压测!step 4 根据压测结果,找到有瓶颈的表,用ddl做下表结构的调整,例如增删索引、直接指定分区键等。索引是否多余2.1.2 CockroachDB 二级索引

数据存储

CREATE TABLE test (      key       INT PRIMARY KEY,      floatVal  FLOAT,      stringVal STRING)INSERT INTO test VALUES (10, 4.5, "hello”)编码:每个TableID(64bit)

test Table ID

1000

key Column ID

1

floatVal Column ID

2

stringVal Column ID

3

Key

Value

/1000/10/2

4.5

/1000/10/3

"hello”

针对空列,写一个只包含 表和主码的key:/1000/10

索引Key

/tableID/indexID/indexColumns[/columnID]CREATE INDEX foo ON test (stringVal) 

Key

Value

/test/primary/10

Ø

/test/primary/10/floatVal

4.5

/test/primary/10/stringVal

"hello”

标签: #apachephoenix