高考前一天考生丢失身份证,深夜民警加班补办
极目新闻记者陆缘通讯员董宏祥高考前一天,即将参加考试的考生身份证却
对于一个分析型数据库,最核心的三个组成部分就是存储引擎、查询引擎和查询优化器,这也是Doris极致性能的决定因素。在此之外,向量化执行引擎的加入,让CPU的能力得到了更充分的发挥,更进一步提升了Doris查询性能。
和大多数分析型数据库一样,Doris也是以列存格式存储数据的。数据按照列进行连续存储,因为类型相同,因此可以获得极高的压缩率,节省磁盘空间。Doris对不同列的数据类型还提供了不同的编码方式,如INT类型会使用BitShuffle的编码方式,而字符串类型会使用字典编码。更进一步,Doris还会自动根据列的值分布情况来切换编码类型。比如对于字符串类型,如果列的去重值比较多,则不再使用字典编码,而直接切换到Plain Text编码,以避免不必要的空间浪费。
【资料图】
从文件组织形式上,Doris的文件格式和Parquet比较类似。一个数据版本会被分割成最大空间为256MB一个的Segment,每个Segment对应一个物理文件。Segment通常分为Header、Data Region、Index Region、Footer几个部分。Data Region 用于按列存储数据,每一列又被分为多个Page,而Page是Doris的最小数据存取单元,如图1所示。
▲图1 Doris文件格式
Index Region负责存储数据的索引。Doris提供了丰富的索引结构来帮助加速数据的读取和过滤。索引的类型大体可以分为智能索引和二级索引两种。其中智能索引是在Doris数据写入时自动生成的,无须用户干预,包括前缀稀疏索引、Min Max索引等。而二级索引是用户可以选择性地在某些列上添加的辅助索引,需要用户自主选择是否创建,比如像Bloom Filter、Bitmap倒排索引等。
前缀稀疏索引是建立在排序结构上的一种索引。存储在文件中的数据是按照排序列有序存储的。Doris会在排序列数据上,每1024行创建一个稀疏索引项,如图2所示。索引的Key即当前这1024行中第一行的前缀排序列的值。当用户的查询条件包含这些排序列是,我们可以通过前缀稀疏索引快速的定位到起始行。
▲图2 Doris前缀稀疏索引和Min Max索引示例
Min Max索引是建立在Segment和Page级别的索引。对于Page中的每一列,Min Max索引都会记录这个Page中的最大值和最小值,同样,在Segment级别也会对每一列的最大值和最小值进行记录。这样当进行等值或范围查询时,可以通过Min Max索引快速过滤掉不需要读取的行。
Bloom Filter(布隆过滤器)是一种需要用户自主选择是否创建的索引。当对某一列创建Bloom Filter索引后,Doris会在page级别创建该列的Bloom Filter结构。Bloom Filter是一种使用固定空间的位图来快速判断一个值是否存在的数据结构,这种数据结构非常适合用于高基数列上的等值查询,比如UUID。
Bitmap也是一种需要用户自主选择是否创建的索引。Bitmap索引是一种基于位图的数据结构,其Key值是实际的列值,而Value值是key在数据文件中的offset。通过Bitmap索引,Doris可以很快定位到列值对应的行号,进行快速取数。这种索引比较合适在基数较低的列上进行等值查询的场景,比如城市等。
除了存储方式和索引结构,Doris在读取逻辑上也有很多优化。比如延迟物化功能会先根据有索引的列,定位到一个数据范围,然后再根据有过滤条件的列进行进一步过滤来缩小数据范围,最后再读取其他需要读取的列。这种方式可以很大程度上减少不必要的数据读取,降低查询请求对I/O的资源消耗。
02查询引擎Doris的查询引擎是基于MPP的火山模型,是从早期版本的Apache Impala演化而来的。在Doris中,一个SQL语句会先生成一个逻辑执行计划,然后根据数据的分布,形成一个物理执行计划。物理执行计划会有多个Fragment,而Fragment之间的数据传输则是由Exchange模块完成的。通过Exchange模块,Doris在执行整个查询的时候就有了数据重分布(Reshuffle)的能力,查询不再局限于数据的存储节点,从而能够更好地利用多节点资源进行并行数据处理。执行框架如图3所示。
▲图3MPP框架执行流程示意图
逻辑执行计划的Agg阶段变成了物理执行计划中的先重分布然后汇总的两个步骤,这个过程和Hadoop是类似的,都是按照相同的Key进行数据重分布。
除了整体的执行框架通过并行设计来提高查询效率外,Doris 还对很多具体的查询算子进行了优化。比如图4种的聚合算子。
▲图4 聚合算子
在Doris中,聚合算子会被拆分成两级聚合。第一级聚合会在数据所在节点先进行一次本地聚合,以减少发送到第二层聚合时需要传输的数据量,而第二级聚合会将Key相同的数据汇聚到同一个节点,进行最终的聚合计算。
在此基础上,Doris还实现了自适应的聚合算法。首先我们要知道,聚合算子是一种阻塞型算子,需要等到全部数据处理完成后,才会将数据发送给上层节点。而自适应聚合算法的意思是,在第一级聚合算子中,如果发现数据的聚合效果很低,即使聚合后也无法有效降低需要传输的数据量,则会自动停止第一级聚合,而将算子转换为一个非阻塞的流式算子,直接将读取到的数据发送到上层节点,从而避免不必要的阻塞等待时间。
针对Join算子,Doris也进行了大量优化,其中Runtime Filter是很重要的一种优化方式。在两个表的Join操作中,我们通常将右表称为BuildTable,而将左表称为ProbeTable。在实现上,通常首先读取右表的数据,在内存中构建一个HashTable,然后开始读取左表的每一行数据,并在HashTable中进行连接匹配,返回符合连接条件的数据。通常来说,左表的数据量会大于右表的数据量。
而Runtime Filter的设计思路,是在右表构建HashTable的同时,为连接列生成一个过滤结构。之后把这个过滤结构推给左表。这样,左表就可以利用过滤结构,对数据进行过滤,从而减少Probe节点需要传输和比对的数据量。这种过滤结构被称为Runtime Filter。针对不同的数据,Doris也实现了不同类型的过滤器,例如In Predicate,Bloom Filter和Min Max。用户可以根据不同场景选择不同的过滤器。Runtime Filter实现逻辑示意图如图5所示。
▲图5Runtime Filter实现逻辑示意图
Runtime Filter可以适用于大部分Join场景,包括节点的自动穿透,将Filter穿透下推到最底层的扫描节点,例如分布式Shuffle Join中,将多个节点产生的Filter进行合并后再下推数据读取节点等。
03查询优化器除了查询执行层方面的优化,Doris 在查询优化器方面也做了大量工作。Doris中的查询优化器能够同时进行基于规则和基于代价的查询优化。在基于规则的查询优化方面,Doris包括但不限于以下优化规则。
1)常量折叠。常量折叠可以预先对常量表达式进行计算,计算后的结果有助于规划器进行分区分桶裁剪,以及执行层利用索引进行数据过滤等。例如将where event_dt>=cast(add_months(now(),-1) as date)折算成where event_dt >=’2022-02-20’[14][15](编写本节时是2022年3月20日晚上)。
2)子查询改写。将子查询改写为Join操作,从而利用Doris在Join上做的一系列优化来提升查询效率。例如select * from tb1 where col1 in (select col2 from tb2) a改写成select tb1.* from tb1 inner join tb2 on tb1.col1=tb2.col2。
3)提取公共表达式。提取公共表达式可以将SQL中的一些析取范式转换成和取范式,而和取范式通常对执行引擎是比较友好,可以将查询条件重组或者下推,减少数据扫描和读取的行数。例如将条件where (a>1 and b=2) or (a>1 and b=3) or (a>1 and b=4)转化成 where a>1 and b in (2,3,4),明显后者的判断速度比前者的快很多。
4)智能预过滤。智能预过滤可以将SQL中的析取范式转换成和取范式并提炼出公共条件部分。这些公共条件可以预先过滤部分数据,从而减少数据处理量。
5)谓词下推也是查询优化器常见的优化手段。Doris中的谓词下推不仅可以穿透算子,更能进一步地下推到存储引擎,利用数据索引进行数据的过滤,如图6所示。
▲图6Doris中的谓词下推示意图
而在基于代价的查询优化方面,Doris主要针对Join算子进行了大量优化。
Join Reorder功能可以通过一些表的统计信息,自动的调整Join的顺序。而Join顺序的调整,会显著降低Join操作中生成的中间数据集的大小,从而加速查询的执行,如图7所示。
▲图7 Doris Join Reorder优化示意图
Colocation Join可以利用数据的分布情况,将原本需要Shuffle后才能进行Join的数据,在本地即可完成Join操作,从而避免了Shuffle时大量的网络数据传输。如图8所示。
▲图8 Doris Colocation Join示意图
Bucket Join是Colocation Join的通用版本。在Colocation Join中,用户需要在建表时就指定表的分布,以保证需要关联查询的若干个表有相同的数据分布。而Bucket Join会更智能地自动判断SQL中的关联条件和数据分布之间的关系,将原本需要同时Shuffle的左右两张表的数据的操作,变成仅将右表数据重分布到左表所在的节点,从而减少数据的移动量。如图9所示。
▲图9 Doris Bucket Join示意图
04向量化执行引擎传统的数据库都是典型的迭代模型,执行计划里面的每个算子通过调用下一个算子的next()方法来获取数据,数据从最底层的数据块中一条一条的读取处理最终返回给客户,它的问题在于每个tuple(也叫元组,是一种常见的编程数据类型,和数组类似,但是元组的元素可以是不同的类型)都要调用一次函数,调用开销太大,而且因为CPU每次只处理一条数据,无法利用[18][19]CPU技术升级带来的新特性,比如SIMD。向量化模型每次处理的是一批数据,这些数据会被保存在一种叫作向量的数据结构里面,然后因为每次处理的是一批数据,因此可以在每个Batch内部可以做各种优化。简单的说,向量化执行引擎 = 高效的向量数据结构(Vector)+ 批量化处理模型(nextBatch)+ Batch内性能优化(例如SIMD等)。
原本向量化执行引擎只是一个概念,是ClickHouse将其变成了现实,率先在数据库产品中实现了向量化执行引擎并展示出强悍性能。通过向量化执行引擎原理的介绍,我们可以看出,向量化执行引擎非常适合基于列存储的OLAP数据库,可以极大的提高并行查询效率。在ClickHouse之后,OLAP数据库实现向量化执行引擎几乎已经成为标配。目前,除了Doris以外,polar-x、TDSQL都声称部分或者全部实现了向量化执行引擎功能。
Doris是在0.15版本引入向量化执行引擎功能的,并在1.0版本中逐渐成熟。根据Doris的演进计划,向量化执行引擎会逐步替换当前Doris的行式SQL执行引擎,以充分释放现代CPU的计算能力,实现更强悍的查询性能。
在绝大多数场景之中,用户只需要将session变量enable_vectorized_engine设置为true,则FE在进行查询规划时就会默认将SQL算子与SQL表达式转换为向量化的执行计划,从而提升SQL执行性能。
关于作者:王春波,资深大数据架构师,现就职于一家互联网公司,任高级数仓工程师,负责电商数仓项目;在银行业、零售行业深耕多年,参与和负责过多家银行、零售数据分析实施项目;“数据中台研习社”号主,《Doris实时数仓实战》《高效使用Greenplum:入门、进阶与数据中台》作者。
关键词:
极目新闻记者陆缘通讯员董宏祥高考前一天,即将参加考试的考生身份证却
在梅西确定加盟之后,迈阿密国际队向苏亚雷斯、布斯克茨和阿尔巴展开了
想必现在有很多小伙伴对于无关紧要的意思方面的知识都比较想要了解,那
行情表现6月7日收盘价当日涨跌幅五日涨跌幅尿素1664 00元 吨-2 63%-3 1
1、没有明确的时间点,明末倭寇骚扰我国东南沿海时就已经开始实行闭关
6月6日,省委老干部局副局长徐维德带领主题教育调研组来金塔县调研,县
1、长征红军不怕远征难,万水千山只等闲。2、五岭逶迤腾细浪,乌蒙磅礴
IT之家6月7日消息,Fifine在印度推出了两款新品麦克风,分别为AMPLITAN
美国农业部发布的全国作物进展周报显示,目前美国玉米优良率显著下降,
茌平区气象台2023年06月07日15时14分发布高温橙色预警信号:目前我区杨
传统非遗和创新科技能碰撞出怎样的火花?科技馆里的非遗又有什么新鲜玩
各类大型考试不仅是广大学子知识比拼的舞台,也是通信圈作弊与反作弊技
同花顺金融研究中心6月7日讯,有投资者向大元泵业提问,汇率跌对公司有
当地时间6月4日,土耳其新任财政部长穆罕默德·希姆谢克表示,土耳其将
在老年中心举办的一项活动是舞会之夜。为老年人举办舞会让每个人都盛装
直播吧6月7日讯据《每日体育报》报道,巴萨正计划向梅西送上正式报价,
Google在博客中宣布,正在推出软件更新,以改善网络连接缓慢时NestWifi
1、个人觉得不管什么产品适合自己的才是最好的,效果当然就因人而异了
1、林崇,教授,博士,青岛大学第二层次特聘教授,博士生导师。美国电
民生加银智造2025增聘基金经理李君海去年跌27 5%
如不能正常浏览请选用IE浏览器 天津北方网讯:重庆:红外相机记录到
近期在岸和离岸人民币兑美元汇率均跌破7。9月15日,央行下调金融机构外
北京时间6月5日,ESPN就曾分析过洛杉矶湖人队是否会在今夏提前续约安东
IT之家注:三星GalaxyZFold和GalaxyZFlip系列是全球首批支持防水的可折
近日,不少网友反映,收到电信运营商温馨提示:2023年北京地区高考