发布时间:2022-06-13 | 阅读:
作者简介 PROFILE
林祺
柏睿数据咨询顾问
深入浅出话DB
✦
经过前文对数据存储的介绍,大家对RapidsDB的数据存储方面有了一定的认知。同时朋友们可能也会思考:作为新一代的分布式数据库,RapidsDB还有没有更硬核的优化手段?抠细节能抠出个三室一厅那种?
好!!本文我们就RapidsDB数据编码方面来看如何做到性能加速。
✦
✦
介绍RapidsDB的数据编码,准确地说,是介绍存在磁盘内的列存储表的数据编码。列存储表的数据以多种不同形式编码存储,包括字典编码、游程编码和值编码。只有某些编码可以直接处理,即直接“操作”,如字典编码、游程编码和整数值编码。
以字典编码为例
对于只有3个不同值的字符串列的一个段,为每个字符串存储一个2位的ID号,ID号被用作字典的参考。当存储在列存储中时,这些ID被紧紧地打包在一起。请参考以下字典:
当它被存储到列段中时,可以表示为打包字符串ID的位向量:
Strings:”red”,”blue”,”green”,”green”,”red”
Strings IDs:0,2,1,1,0
Bit vector:00 10 01 01 00 (2 bits per string ID)
作为直接对编码数据进行操作的例子,RapidsDB可以对字符串字典编码的列段执行过滤操作,比如说“t.a=’xyz’”,方法是首先找到字典中每个条目的过滤结果,然后在扫描该段时,查询执行系统简单地获取t.a中每个值的编码ID号,并使用它来查找在字典的初始扫描中计算的该ID的字符串比较结果。这往往比实际情况中的字符串比较要快得多。其他类型的操作也可以直接在编码数据ID值上完成,包括比较进行分组操作所需的ID值。更多细节可自行拓展了解。
在列存储扫描之外的RapidsDB中的大多数查询处理都是一次一行地完成的。对编码数据的列存储处理以矢量化的方式完成,其中来自一列的大批量数据在一个或多个相对简单的循环中处理。与一次一行的处理相比,这些循环对现在CPU更加友好,通过降低指令数量,提高了高速缓存使用率,并提高了处理器指令流水线的效率。
基于上述编码,通过使用特殊的编码处理技术以及支持英特尔AVX2指令集的处理器上的单指令多数据(SIMD)指令,使包括过滤和聚合在内的某些操作可以在非常高效的状态下运行。
硬件上的SIMD不是编码数据优化的唯一核心,即使没有SIMD的支持,对编码数据的操作性能也会提高几倍到30倍;使用了SIMD则可以进一步提升性能,带来至少2-3倍的增益。具体优化结果将取决于数据及查询。个别查询的一些部分可能不需要对编码数据进行操作,因此用户体验到的加速效果可能会有所不同。
默认情况下,对数据编码的操作是数据库内部自动执行的。用户不需要更改任何设置就能从中受益。对数据编码使用操作是查询在系统运行时生成的,而不是由查询优化器做出的。
编码数据的查询优化只能在列式表中体现,需要具备以下一个或多个组件:
过滤器Filters
分组 Group by
聚合 Aggregates
聚合表达式
分组表达式
整数列上的Star joins
不管运行中的编码列不同值的数量是多少,都可以对编码数据进行优化操作。编码中不同值的数量越少,优化性能越好。这是因为当字典变小时,意味着列存储数据被压缩到更小的尺寸,进而查找表过程中更容易适配到处理器的高速缓存。
它通过使用了几个包含性能优化的组件从而在对编码数据的操作中提升了性能:
如果再加上一张列式表f,也可以从编码数据的连接操作中得到性能优化。查询示例:
这个查询是星型模型Star joins的一个简单例子。如果用户使用星型模型Star joins做关联,并且关联键是整数类型,那么查询就可以在编码数据的操作中得到性能优化。简单说明,这里是使用group by子句和聚合函数从编码数据的连接操作中加速性能。