全局索引

 

目录

索引表相关介绍

单机表索引:

本地分区索引(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)的分布式数据库来说,如何在机器间有时钟差异的情况下,仍能维持时间戳(即版本号)在全局范围内的前后一致性,这是一个很重要的问题。

### 局部索引与全局索引的区别及其应用场景 #### 1. 定义与基本概念 局部索引(Local Index)是指其数据分布与分区表的数据分布一致的索引。它通常存储在同一分区内,因此访问效率较高[^2]。 全局索引(Global Index)则是独立于分区表数据分布的一种索引形式,它可以跨多个分区进行定义和管理[^4]。 #### 2. 存储方式差异 局部索引的存储位置与其对应的分区表数据紧密关联,即每个分区上的数据都有相应的局部索引部分。这种设计减少了跨节点操作的可能性,从而提升了查询性能[^1]。相比之下,全局索引并不依赖于底层数据的分区策略,而是按照自身的规则分布在各个节点上。 #### 3. 查询性能对比 当执行涉及单一分区的操作时,局部索引能够显著降低延迟并减少资源消耗,因为无需跨越不同分区获取额外信息。然而,在多分区联合查询或者复杂条件过滤的情况下,如果使用的是局部索引,则可能需要多次扫描不同的分区;而此时采用全局索引可能会更加高效,因为它能更灵活地覆盖整个数据集。 #### 4. 维护成本分析 由于局部索引紧耦合到具体的分区之上,所以在新增加或删除某些特定分区的时候,维护起来相对简单快捷。但是,一旦涉及到大规模调整比如重新划分现有分区等情况下的变更处理就会变得较为繁琐。另一方面,尽管修改全局索引可能导致更大范围的影响,但由于它是分离式的架构特性决定了它的灵活性更高一些,在面对频繁变动的需求场景下或许更具优势。 #### 5. 应用场景举例说明 - **适合使用局部索引的情况** - 当应用程序经常针对单一固定分区内的记录做检索工作时; - 或者说业务逻辑本身就倾向于按时间序列或者其他自然分割维度来组织数据的情形之下。 - **推荐考虑全局索引的应用场合** - 如果用户的查询模式更多样化且难以预测具体会落在哪个单独分区之内; - 又或者是存在大量基于非主键字段作为筛选依据的SQL语句运行需求的话,则应该优先选用全局索引来满足这些复杂的查找请求。 ```sql -- 创建局部索引的例子 CREATE INDEX local_idx ON partitioned_table(column_name) LOCAL; -- 创建全局索引的例子 CREATE GLOBAL INDEX global_idx ON partitioned_table(column_name); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值