全局索引

 

目录

索引表相关介绍

单机表索引:

本地分区索引(Local Partitioned Index):

全局非分区索引(Global Non-Partitioned Index)

全局分区索引(Global Partitioned Index)

分布式场景下全局索引和本地索引的对比优势

本地索引唯一性约束

扫描开销:

全局索引优势:

全局分区索引的实现方案

面临的问题


索引表相关介绍

单机表索引:

本地分区索引(Local Partitioned Index):

 

全局非分区索引(Global Non-Partitioned Index)

全局分区索引(Global Partitioned Index)

索引的分区模式是完全独立的,和主表的分区没有任何关系,因此对于每个索引分区来说,里面的某一个键都可能映射到不同的主表分区(当索引键有重复值时),索引分区和主表分区之间是“多对多”的对应关系。

employee表按照emp_id做了范围分区,同时在emp_name上做了全局分区索引。可以看到同一个索引分区里的键,会指向不同的主表分区。类似两张相关联的表,后面会提到数据更新的一致性问题。

由于全局索引的分区模式和主表的分区模式完全没有关系,看上去全局索引更像是另一张独立的表,因此也会将全局索引叫做索引表

分布式场景下全局索引和本地索引的对比优势

本地索引唯一性约束

本地索引只能在一个主表分区内保证索引键的“唯一性约束”,无法在全表范围内保证索引键的唯一性约束

 

有些数据库在分区表中会增加限制,要求主键和唯一索引的定义中必须包含主表所有的分区键字段。有了这个限制,索引中的某一个键所对应的索引数据只可能存在于一个分区中,因此只要在每一个分区内保证唯一性约束,即可在全表范围内保证唯一性约束。

大大增加了开发人员的烦恼,因为它会导致主键和唯一索引的可选范围大大缩小(只能是主表分区键的“超集”),很多业务需求因此无法满足,这也是本地索引最被诟病的地方。

扫描开销:

某一个索引键值在所有分区的本地索引上都可能存在,任何索引扫描必须在所有的分区上都做一遍,以免造成数据遗漏。

这会导致索引扫描效率低下,并且会在全局范围内造成CPU和IO资源的浪费。采用“分区间并行”的手段可以提高效率,但不能从根本上解决这个问题

比如分成1024片,那么要扫描1024分片表对应的索引表。类似join。一个是3层*1024,一个是4层*1

 

全局索引优势:

对于全局索引来说,可以为索引数据指定自己的分区方式,并且索引的分区键一定是索引键的子集,对于某一个索引键来说,由于包含了所有的索引分区键,它的数据只可能落在一个固定的索引分区中,因此只要在每一个索引分区内保证唯一性约束,就可以在全表范围内保证唯一性约束。而单个索引分区内只有一个索引数据结构,很容易保证唯一性约束,因此问题就得到了解决。

 

全局索引能保证某一个索引键的数据只落在一个固定的索引分区中。对于索引键值的范围扫描,我们希望索引扫描按单向顺序在每个分区内都只执行一次,而不必在索引分区之间来回穿梭,因此我们要求索引的分区键是索引键的“前缀(Prefix)”:比如索引键是”a,b”,那么索引的分区键可以是”a”或者”a,b”,但不能是”b”,即要求分区的排序规则和索引树的排序规则一致。这样一来,无论是针对固定键值的索引扫描,还是针对一个键值范围的索引扫描,都可以直接定位出需要扫描的一个或者几个分区,而不是像本地索引一样盲目地在所有分区上扫描,这样就解决了本地索引面临的问题。

全局索引也面临一些问题,主要是架构复杂,实现难度大,以及由此引发的一些相关问题,比如当索引数据和对应的主表数据位于不同的机器时,在事务内会面临数据一致性和性能方面的挑战。但考虑到全局索引给数据库使用者带来的巨大便利,付出一点代价也是值得的

本地索引和全局索引的适用场景是不一样的:

本地索引比较适合“索引键包含主表所有的分区键字段”这种特殊情况。

除了上面的特殊情况之外的其它场景,全局索引更加合适。

可以说,全局索引具有更强的通用性。

 

全局分区索引的实现方案

面临的问题

每一个主表分区和索引分区都可能分布在不同的机器上,比如“N个主表分区+M个全局索引分区”这种多对多的复杂情况,可能是(N+M)台物理机器上形成的(N*M)种索引键到主表分区的映射关系,这会带来诸多挑战:

  • 如果一个事务中要修改的N条记录分别位于N台不同的机器上,而它们对应的全局索引数据又位于另外M台不同的机器上,如何在这(N+M)台机器间保证主表数据和索引数据的同步更新?

  • 还是上面所说的主表数据和索引数据分布在不同机器的场景,在保证数据一致性的前提下,如何进一步缩短跨机器访问的时间,进一步提高查询效率?

  • 如何保证全局索引数据在全局范围内的读写一致性?一台机器上更新的索引数据,如何确保一定能被其它机器上后续的访问者读到?

解决方案

问题1-方案

如何保证主表数据和索引数据的跨机器同步更新。这个问题的本质,其实是分布式数据库中“分布式事务一致性”问题,主表数据和索引数据是同一个事务中的两部分数据,当它们分布在不同的机器上时,分布式事务需要保证事务的原子性(Atomicity):两部分数据要么全部更新成功,要么全部失败,不会因事务异常而导致主表数据和索引数据的不同步。

问题2-方案

索引数据和主表数据分跨机器访问时的效率问题。这里面临的最大挑战就是分布式事务的网络延迟和多次日志落盘,而这种物理开销是没有办法完全消除的,为此Google在F1的论文中明确说明不推荐太多的全局索引,并且应尽量避免对有全局索引的表做大事务访问。

问题3-方案

最后一个问题,则是分布式数据库中全局(跨多台机器)的读写一致性问题。实现了快照隔离级别(Snapshot Isolation)和多版本并发控制(MVCC)的分布式数据库来说,如何在机器间有时钟差异的情况下,仍能维持时间戳(即版本号)在全局范围内的前后一致性,这是一个很重要的问题。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章