各位同行朋友,本篇是本系列的,一篇,也是最舒服的一篇,因为讲内容是自动优化,也就是不需要DBA主动干预,数据库会没事就给自己做优化!是不是有种躺赢的感觉?让本人给大家汇报数据库到底是怎么实现自动优化的?
柏睿数据内存分布式数据库RapidsDB的自动优化体现在2个阶段:
数据入库过程
入库过程的自动优化解决2个常见的OLAP型MPP数据库问题,传统的数控则需要外部手段或者手工执行命令来实现相同的优化效果:
1、自动优化小批量写入(比如单行插入)过程,解决高频小数据量写入的性能低下问题;
2、自动优化数据入库前排序入库过程,解决因新数据无序写入产生的查询性能不高问题。
RapidsDB实现的方式如下:
跟其他友商分布式数据库的列存储实现不同,RapidsDB将新写入的数据先将它们以跳表的方式临时存储在内存中。这个操作由数据库后台自动处理的,这些以行存方式的跳过列表数据,可以对读取可见。
具体一点,向列存表插入数据时,数据会先写入临时的行存跳表或创建新的列存储支持行段。至于是临时表还是新建行段,数据库引擎需要由根据插入数据量大小和列存储索引的当前状态的自动触发确定的。每个数据分区16 MB,是 INSERT 或 LOAD DATA 写入数据优化的默认阈值。当超过这个阈值时,当前外部写入的数据就会在内存经过排序后,直接写入新建的行段,反之则临时存放在行存跳表中,经过超时或者新来数据达到阈值后,写入列存行段中。
经过上述操作,数据入库过程的自动优化完成。
数据入库后
入库过程后的自动优化,就是为了解决传统分布式数据库甚至Hadoop平台也非常常见的:在用户使用一段时间后,发现如果没有对数据库的存储进行人工定时维护,则会引起性能大幅下降的问题,RapidsDB的3个自动优化手段,就是解决核心的3个性能影响因素:
1、无论做增删改操作,数据库都会自动对相关的列存行段中的数据自动重新排序,保证最佳的查询性能;
2、当列存行段内重新排序完成后,其外的行段组会重新做排序组织,进一步使数据有序,二次优化性能;
3、经过上述2点的优化,有序数据使压缩率得到提升,数据文件也得到合并,数据文件个数同时也会减少。IO读写性能可以在整个使用过程中,一直保存在极高的状态中。
基本实现手段如下:
我们都知道如果表中的行在所有行段中都是全局排序的,那么列式表的性能,。实际上,在连续写入的情况下,维持这样的顺序是极难的。
RapidsDB使用了一种,的算法,允许它在新增或更新数据时尽可能保持有序。这个过程被称为background merger,并且为使行段的数据顺序能够得到持续优化,则该过程会一直在后台自动运行。
当background merger在运行过程中,在库内数据被增删改等改变时,它会停止到当前任务并且重新开始。鉴于每次只处理一小块行段数据,所以被停止的任务影响的只是少量的数据。只有在大量的更新工作负载下,重新排序处理效率才会显著减慢,这是因为另一个机制pessimistic merger会锁定当前正在处理的行段。用户也可以通过运行命令OPTIMIZE TABLE手动触发pessimistic merger。我们将在下面解释如何决定是否有必要进行该指令,并如何运行它。
RapidsDB使用sorted row segment group(排序行段组)的概念来描述参与排序的一组行段。即行段重新排序的过程,并且对于一个行段而言,其最小的行号不小于其之前的任何行段中,的行号,则这些行段形成排序的行段组。这里所描述的一行比另一行小,是代表该行的CLUSTERED COLUMNSTORE键的列值比另一行的列值小。
如果数据有一个,的全局顺序,它将由一个排序的行段组组成。如果刚入库的原始数据是以完全随机的顺序排列的,那么它会包含与行段一样多的排序行段组。background merger的任务逻辑就是重新组织行段之间的行,即尽量减少排序的行段组的数量。
以下面的例子直观介绍:
要检查特定表的已排序行段组的当前状态,请在CLI环境中运行SHOW COLUMNAR MERGE STATUS FOR来查看:
让我们仔细看结果的第一行,我们知道存储在分区0上的表的切片具有3个有序的行段组,一个由741个行段组成,一个由16个行段组成,,一个由1行段组成,共计758个行段。考虑这种有序的行段组对非常简单查询的影响:
根据排序行段组的定义,第一个排序的行段组最多包含一个包含user_group = 15的行的行段,除非user_group = 15位于两个行段的边界上,或者如果存在较大数据倾斜并且几个行段仅由user_group = 15的行组成。类似的,第二排序行段组中最多一个行段包含相关行。这样,总共758个行段中只有三个将被打开和具体化。虽然本例中的查询非常简单,但类似的推理同样适用于复杂查询中。
现在我们看一下分区2上有序的行段组。很明显,它的优化程度远远低于剩下的2个,类似上面所示的选择查询将会导致物化8个行段。如果启用了background merger,并且没有或者少量工作负载同时运行,那么这个分区将会在几秒钟内得到优化。然而,在数据库执行大量的增删改任务时,background merger的处理性能会被影响。在这种情况下,不如通过手动触发pessimistic merger,让增删改任务和后台优化任务前后脚独立完成更合理:
如果当我们执行OPTIMIZE TABLE时运行SHOW COLUMNAR MERGE STATUS,那么我们将会看见其作用:
新出现的一行代表分区3上正在进行一个手动合并,此时已经完成了53.12%的工作任务。
当完成合并任务后,现在情况更好了:
请注意,在本例中,没有任何分区被合并到单个有序的行段组中。其原因是,两种不同的合并方式均采用一种,算法,该算法被优化为在并发写入的情况下进行小的分批次工作,并将数据保持在几个有序的行段组中,而不是试图将所有数据合并到单个有序的行段组中。如果可以牺牲一些数据处理时间来获得更高的查询性能,则可以运行手动命令,将每个分区上的数据合并到一个有序的行段组中:
此时,任何选择查询将只具体化每一个分区的一个行段。
当向列式表中插入少量行时,使用内存中行存储支持的段来存储行。当这个以行存储为基础的段被填满时,后台刷新程序background flusher会定期将这些行刷新到磁盘中。通过运行OPTIMIZE TABLEFLUSH,可以手动将受行存储支持的段刷新到磁盘中。
至此,例子中数据表t的后台自动排序完成了。整个过程中,数据库无须用户干预,仅通过自动优化实现了高性能。
目前,RapidsDB已经在国有某大行普惠金融项目应用中运行超过10个月,产品自动优化证明了它的能力和价值。中间经历过几次10TB级的数据加载,每天10GB级的数据新增和更新,以及定时的滚动式删除。过程中,技术团队无需对数据库做任何优化干预,相同场景的数据操作没有任何性能下降的迹象!