前言
作为阿里云自研的自研数据平台,TableStore有可靠、海量存储以及易于扩展等特点。但是由于数据模型的限制,原生的TableStore只能基于主键做查询。如果有其他查询分析需求用户也只能借助如Dataworks、Data Lake Analytics。
基于上面的痛点,TableStore在2018年末推出了两大在线索引功能:GlobalIndex(全局二级索引)与SearchIndex(多元索引),这两个功能大大地弥补了原先TableStore查询方式单一的缺点。但是用户在选型的时候也会有所迷惑,两个功能都包含了“索引”二字,那么又有什么区别呢?本文将针对这个问题做详细剖析。
查询场景
原生TableStore
对于一个三主键的表,假设三列主键分别为X、Y、Z,对于这种设计我们可以使用的查询功能相对比较简单:
- 精确查询,指定X、Y、Z的值
-
范围查询,必须遵循最左匹配原则
- 指定X的值,Y与Z为范围
- 指定X与Y的值,Y为范围
- X、Y、Z均为范围
全范围值指(MIN~MAX)。
对于原生的TableStore提供的查询功能,优缺点整理如下:
优点 | 1. 性能极佳,根据用户指定的主键可以定位到具体分片 |
---|---|
缺点 | 1. 查询功能相对单一,如果需要指定其他列的话需要使用Filter功能,在大数据量的情况下,性能较差 2. 不能修改主键结构 |
但是在很多场景下,需要查询非主键列的属性列,这个时候上述主表结构就不能满足需求了,为了解决这个问题,我们开发了类似于关系型数据库的二级索引(GlobalIndex)。
GlobalIndex
GlobalIndex使用的是额外的一张TableStore表来实现的,所以索引表的数据模型与TableStore的表完全一致。用户可以指定任意列(原表的主键列或属性列)作为索引表的主键。
如我们原表有以下的几列:
- 一列主键X。
- 三列属性列Q、W、E
我们创建的索引的主键为:Q、X(这里加上原表主键X是为了防止Q列的重复,因为属性列Q不一定唯一,但是Q与X的组合是一定是唯一的),则我们通过索引表可以完成的查询组合为:
- Q范围查询,X范围查询
- 指定Q的值,X为范围
- 指定Q和X的值
创建了索引表后,在原先只能通过主键进行查询的基础上,扩充了查询的多样性。
为了不影响用户数据写入延迟,我们采用了异步同步数据的方式。也就是说用户在将数据写入原表成功后,是立刻返回的,而数据则是通过我们内部的同步链路同步到索引表。所以说数据写入成功后到索引数据可见,是有一定的延迟的,这个延迟一般为毫秒级别。
GlobalIndex的优缺点总结如下:
优点 | 1. 索引表是TableStore的表实现的,通过索引查询的性能极佳 2. 通过索引可以进行大范围查询(getRange) 3. 增加了通过属性列查询的能力 |
---|---|
缺点 | 1. 如果查询需求过于多变,则需要创建多张索引表 2. 查询固定,不能自由组合查询 3. 查询功能略为局限,只能是范围、精确值查询,不能做GEO、分词等查询 |
GlobalIndex在原有TableStore表的基础上,为用户提供了更多的查询选择,并且索引的性能与原生的TableStore表相当,比较适合索引需求相对简单并且对性能要求很高的用户。
多元索引(SearchIndex)
GlobalIndex虽然查询能力上有所增强,但是在某些查询功能上还是无法满足需求,比如分词查询、多字段自由组合查询、模糊查询、地理位置查询等,为了支持更多的查询能力,我们为TableStore增加了多元索引,下面我们来看一下多元索引。
与GlobalIndex不同,SearchIndex底层使用的是自研索引引擎,使用了倒排索引、行存、列存等技术来优化查询。在数据组织方面与TableStore类似,SearchIndex底层也是使用“分片”的形式将数组织在一起,但是与GlobalIndex不同的是,默认的话写入的数据时通过原表主键来确定分区的。也就是说如通过一个条件查询完整结果的话,需要对所有“分片”进行查询并合并结果。
虽然查询性能上,特别是一些简单条件查询SearchIndex是要比GlobalIndex要差,但是其优势在于查询功能的强大。如果用户需要对索引列进行多种组合查询,或这一些更高级的功能,如:GEO地理位置查、分词查询等,都只需要创建一个索引就可以完成。
在查询方面,SearchIndex比较适合如下的一些场景:
- 需要对查询做任意组合
- 需要有or的查询,如X=a OR X=b的场景
- 需要GEO地理位置查询
- 需要对字符串分词查询
与GlobalIndex类似,数据同步到SearchIndex也是异步的。由于SearchIndex内部实现的原因,数据写入到SearchIndex有一个索引构建的过程。所以除了同步链路的延迟,还需要加上索引构建的延迟,整个延迟的话在秒级别。
SearchIndex的优缺点整理如下:
优点 | 1. 支持的查询比GlobalIndex更加丰富:OR查询、分词查询、GEO地理位置查询等 2. 只需要一个索引就可以满足所有查询需求 3. 多样性的排序需求 |
---|---|
缺点 | 1. 在默认情况下,一个查询条件需要查询所有“分片”才能获得全部结果 2. 大范围查询扫描支持不如GlobalIndex强大 3. 同步延迟比GlobalIndex长 |
与GlobalIndex相比,SearchIndex在查询功能的多样性上要略胜一筹,但是在一些特定的场景,如大范围扫描索引、简单条件匹配以及对同步延迟敏感的情况下,GlobalIndex性能更佳。在数据延迟方面由于内部实现的原因,SearchIndex数据延迟为秒级别,而GlobalIndex则为毫秒级别。
总结
我们将两种索引的不同点与各自的优缺点整理成如下的表,共大家参考。
GlobalIndex(全局二级索引) | SearchIndex(多元索引) | |
---|---|---|
查询灵活性 | 只可以使用创建索引时的给出的索引组合进行查询, 如果需要其他组合则需要再创建新的索引表 | 可以对索引字段做任意组合查询 |
查询性能 | 通过索引键可以定位到对应“分片”,性能极佳 | 不指定路由的话需要查询所有“分片” |
大范围扫描 | 支持,性能与原生TableStore一致 | 支持,但性能不及全局二级索引 |
数据可见延迟 | 毫秒级 | 秒级 |
分词查询 | 不支持 | 支持 |
GEO地理位置查询 | 不支持 | 支持 |
数据一致性 | 最终一致 | 最终一致 |