文接上回,我们一起由浅入深地了解了柏睿数据分布式内存数据库RapidsDB在数据存储方面的多种优化方式。根据软件基本方法:程序 = 数据结构 + 算法,本章内容就为大家介绍RapidsDB是如何使用优化算法提升查询性能的。

■首先,我们需要了解RapidsDB的代码生成到底做了什么事情

相对于使用传统解释器的数据库执行模型,RapidsDB嵌入了编译器来生成高效机器代码,从而实现更底层的优化,这个过程不是常规的语法解释器可以实现的。在默认情况下,查询语句会首先被解释,再经过后台异步编译以便在以后的执行中使用。这种方法加速了长时间的复杂查询的执行时间,同时为以后的使用提供了高效的查询计划。

如上所述,RapidsDB在首次处理某个查询语句时,会异步优化并编译查询以备后用。这带来了最小的开销,这与需要处理的数据量大小无关,而是与查询的复杂程度相关。代码生成过程包括从查询中提取参数,然后将规范化的查询转换为系统定制的数据库中间表示方式。具有相同语法结构的后续请求就可以重用该计划,以便达到优化的效果。

代码生成适用于所有数据操作语言(DML)查询。例如,RapidsDB在CREATE TABLE和ALTER TABLE语句期间生产代码。这些数据定义语言(DDL)产生的编译代码,就可减少类似DML查询的执行时间。

■其次,我们需要了解语法解释器模式对代码生成的影响有多大

在本节中,会介绍当RapidsDB遇到新的查询语法结构时,是如何进行工作的。

●当解释器模式interpreter_mode被设置为编译compile时:

在这种模式下,RapidsDB会在首次遇到查询的时候编译查询语句。如下例所示,查询SELECT * FROM t WHERE col = 1;本次运行需要更长时间才能完成。

上面例子是在初次中编译开销的结果。注意下面例子中,在第二个和第三个查询,WHERE子句是不同的,但是两个查询语句的结构是相同的。因此,RapidsDB重用第二个查询的计划来运行了第三个查询。

打开网易新闻 查看精彩图片

●当解释器模式interpreter_mode被设置为解释优先interpret_first:

在这种模式下,当首次遇到某查询时,RapidsDB会并行解释和编译查询。查询以解释模式运行,直到查询形状的编译完成。下面例子中,第一个查询SELECT * FROM t WHERE col = 1;的查询速度会比前面示例中的第一个查询速度更快。

打开网易新闻 查看精彩图片

■最后,我们一起初探代码生成的实现方法

●代码生成的架构

代码生成使用专门的编程语言MPL,选用这门语言的原因是使用简单、管理严密。SQL操作符树将会被直接转化为抽象语法树,以化解在查询编译时对昂贵的解析和语义解析的需求。

除了语言的简单性以外,其还受益于将许多关系操作作为原语公开,如“索引查找”和标量操作,如“BIGINT加法”。这些操作符是与服务器一起静态编译的,可以很容易地组合成查询。这样,许多编译工作就可以提前完成。

●数据库字节编码

编译查询时,RapidsDB首先将MPL展开成紧凑的格式,也可以称为RapidsDB字节码(MBC)。这种格式的执行计划可以轻易的进行序列化、解释或转换为LLVM位代码,以便编译成x86_64机器代码。这种直接解释字节码基本消除了第一次运行查询的成本,但会影响查询执行的性能:

打开网易新闻 查看精彩图片

在这个例子中,第一个请求没有额外的延迟产生,因为该查询被解释了。

打开网易新闻 查看精彩图片

上面例子的第一个请求的额外延迟是代码生成的结果。但是,后续的请求速度是上门解释执行的速度的两倍。

回看我们的项目实例,在国有大行普惠金融项目应用中,50%左右的查询是结构重复的查询,而RapidsDB依托代码生成的优化特性降低了50%-80%的查询时间,获得很好的使用体验。