Doris ——SQL原理解析

目录

前言

一、Doris简介

二、SQL解析简介

2.1 词法分析

2.2 语法分析

2.3 逻辑计划

2.4 物理计划

三、Doris SQL解析的总体架构

四、Parse阶段

五、Analyze阶段

六、SinglePlan阶段(生成单机逻辑Plan阶段)

七、DistributedPlan计划(生成分布式逻辑阶段)

7.1 DistributedPlan 概述

7.2 四种join算法:

7.2.1 Broadcast Join

7.2.2 Shuffle Join

7.2.3 Bucket Shuffle Join

7.2.4 Colocate Join

7.3 分布式逻辑计划的核心流程

7.3.1  PlanNode

7.3.2  ScanNode

7.3.3 HashJoinNode

八、Schedule阶段

8.1  prepare阶段

8.2 computeScanRangeAssignment阶段

8.3 computeFragmentExecParams阶段

8.4  create result receiver阶段

8.5  to thrift阶段

九、总结

前言

    下文主要介绍了Doris SQL解析的原理。阐述了词法分析,语法分析,生成单机逻辑计划,生成分布式逻辑计划,生成分布式物理计划的过程。对应代码实现是Parse, Analyze, SinglePlan, DistributedPlan, Schedule这五个部分。

一、Doris简介

     Apache Doris是一个基于MPP架构的高性能、实时的分析型数据库,能够较好的满足报表分析、即席查询、统一数仓构建等使用场景。Doris整体架构非常简单,只有FE和BE两类进程。FE主要负责用户请求的接入、查询解析规划、元数据的管理、节点管理相关工作。BE主要负责数据存储、查询计划的执行。

    在 Doris 的存储引擎中,用户数据被水平划分为若干个数据分片(Tablet,也称作数据分桶)。每个Tablet 包含若干数据行。多个 Tablet 在逻辑上归属于不同的分区(Partition)。一个 Tablet 只属于一个 Partition。而一个 Partition 包含若干个 Tablet。Tablet 是数据移动、复制等操作的最小物理存储单元。

  官网链接指路:

Doris 介绍 - Apache Doris

二、SQL解析简介

     sql解析指的是:一条sql语句经过一系列的解析最后生成一个完整的物理执行计划的过程。解析过程主要包括以下四个步骤:词法分析,语法分析,生成逻辑计划,生成物理计划。

  • 词法分析:解析原始SQL文本,拆分token
  • 语法分析:将token转换成抽象语法树(AST)
  • 逻辑查询计划:
  • 单机逻辑查询计划:对AST经过一系列优化(比如:谓词下推等)成查询计划,提高执行性能和效率
  • 分布式逻辑查询计划:根据分布式环境(数据分布信息、连接信息、join算法等)将单机逻辑查询计划转换成分布式
  • 物理查询计划:在逻辑查询计划的基础上,根据数据的存储方式和机器的分布情况生成实际的执行计划

Doris SQL 解析架构具体介绍如下:

2.1 词法分析

     词法分析主要负责将字符串形式的sql识别成一个个token,为语法分析做准备。


select ......  from ...... where ....... group by ..... order by ......SQL的Token 可以分为如下几类:
○ 关键字(select、from、where)
○ 操作符(+、-、>=)
○ 开闭合标志((、CASE)
○ 占位符(?)
○ 注释
○ 空格

2.2 语法分析

    语法分析主要负责根据语法规则,将词法分析生成的token转成抽象语法树(Abstract Syntax Tree),如图2所示。

2.3 逻辑计划

     逻辑计划负责将抽象语法树转成代数关系。代数关系是一棵算子树,每个节点代表一种对数据的计算方式,整棵树代表了数据的计算方式以及流动方向

2.4 物理计划

     物理计划是在逻辑计划的基础上,根据机器的分布,数据的分布,决定去哪些机器上执行哪些计算操作。Doris系统的SQL解析也是采用这些步骤,只不过根据Doris系统结构的特点和数据的存储方式,进行了细化和优化,最大化发挥机器的计算能力。

   

三、Doris SQL解析的总体架构

     Doris SQL解析具体包括了五个步骤:词法分析,语法分析,生成单机逻辑计划,生成分布式逻辑计划,生成物理执行计划。具体代码实现上包含以下五个步骤:Parse, Analyze, SinglePlan, DistributedPlan, Schedule

四、Parse阶段

   Parse阶段主要涉及三部分工作:

  • 构建词法解析器
  • 词法分析,将 doris sql中的关键词识别成一个个token
  • 进行语法解析,将词法分析生成的token转成抽象语法树AST

五、Analyze阶段

   SQL 语句被解析成AST之后,会被交给 StmtExecutor进行一些前期的处理和语义分析,为生成单机逻辑计划做准备,大概会做下面的事情:

  • 元信息的识别和解析

       识别和解析sql中涉及的 Cluster, Database, Table, Column 等元信息,确定需要对哪个集群的哪个数据库的哪些表的哪些列进行计算。

  • SQL 的合法性检查

       窗口函数不能 DISTINCT,投影列是否有歧义,where语句中不能含有grouping操作等。

  • SQL 重写

        比如将 select * 扩展成 select 所有列,count distinct转成bitmap或者hll函数等。

  •  函数处理

        检查sql中包含的函数和系统定义的函数是否一致,包括参数类型,参数个数等。

  • Table与Column别名处理
  • 类型检查和转换

     例如:二元表达式两边的类型不一致时,需要对其中一个类型进行转换(bigint和decimal比较,bigint类型需要转换成decimal)

    总结,对AST进行analyze后会再进行一次rewrite操作,进行精简或者是转成统一的处理方式

六、SinglePlan阶段(生成单机逻辑Plan阶段)

     此阶段主要是根据AST抽象语法树生成算子数。树上的每个节点都是一个算子。如下图所示,ScanNode代表着对一个表的扫描操作,将一个表的数据读出来。HashJoinNode代表着join操作,将小表广播到大表所在的每个节点,内存中构建哈希表,然后遍历大表每条记录做关联。Project算子表示投影操作,代表着最后需要输出的列,下图中的sql表示只用输出citycode这一列。

SinglePlan阶段主要做了如下几项工作:

  • Slot 物化:指确定一个表达式对应的列需要 Scan 和计算,比如聚合节点的聚合函数表达式和 Group By 表达式需要进行物化(Slot:计算槽,是一个资源单位, 只有给 task 分配了一个 slot 之后, 这个task才可以运行)
  • 投影下推:BE在Scan 时只会Scan必须读取的列
  • 谓词下推:在满足语义正确的前提下将过滤条件尽可能下推到Scan节点
  • 分区,分桶裁剪:根据过滤条件中的信息,确定需要扫描哪些分区,哪些桶的tablet
  • Join Reorder:对于 Join操作, Doris会根据行数调整表的顺序,将大表放在前面。在保证结果不变的情况,通过规则计算最优(最少资源)join 操作
  •  Sort + Limit 优化成 TopN:对于order by limit语句会转换成TopN的操作节点
  • MaterializedView 选择:会根据查询需要的列,过滤,排序和 Join 的列,行数,列数等因素选择最佳的物化视图
  • 向量化执行引擎选择:基于现代CPU的特点,重新设计列式存储系统的SQL执行引擎,从而提高了CPU在SQL执行时的效率,提升了SQL查询的性能

  • Runtime Filter Join:Doris 在进行Hash Join 计算时会将小表广播到大表所在的各个节点上,构建一个内存哈希表,然后流式读出大表的数据进行Hash Join。而 RuntimeFilter是在右表生成哈希表的时候,动态生成一个基于哈希表数据的过滤条件,将该过滤条件下推到大表的数据扫描节点,从而减少扫描的数据量,避免不必要的I/O和网络传输。

七、DistributedPlan计划(生成分布式逻辑阶段)

7.1 DistributedPlan 概述

      (1) 根据分布式环境,将单机的PlanNode树(planNode : 逻辑算子)拆分成分布式PlanFragment树(PlanFragment用来表示独立的执行单元)

     (2)每个 PlanFragment 由 PlanNodeTree 和 Data Sink 组成。Plan分布式化的方法是增加 ExchangeNode,PlanNodeTree执行计划树会以 ExchangeNode为边界拆分为 PlanFragment。  ExchangeNode主要是用于BE之间的数据交换与共享,类似 Spark 和 MR 中的 Shuffle。

      (3)DistributedPlan阶段的主要目标是最大化并行度和数据本地化。主要方法是将能够并行执行的节点拆分出去单独建立一个PlanFragment,用ExchangeNode代替被拆分出去的节点,用来接收数据。拆分出去的节点增加一个DataSinkNode,用来将计算之后数据传送到ExchangeNode中,做进一步的处理。

     (4)DistributedPlanner中最主要的工作是决定Join的分布式执行策略:Broadcast Join,Shuffle Join,Bucket Shuffle Join,Colocate Join以及增加 Aggregation 的 Merge 阶段。

7.2 四种join算法:

    对于查询操作来说,join操作是最常见的一种操作。Doris目前支持4种join算法:Broadcast Join,Shuffle Join,Bucket Shuffle Join,Colocate Join

7.2.1 Broadcast Join

   小表进行条件过滤后,将其广播到大表所在的各个节点上,形成一个内存Hash 表,然后流式读出大表的数据Hash Join。Doris会自动尝试进行 Broadcast Join,如果预估小表过大则会自动切换至 Shuffle Join。

7.2.2 Shuffle Join

    大表和大表join时,一般采用hash partition join。它遍历表中的所有数据,计算key的哈希值,然后对集群数取模,选到哪台机器,就将数据发送到这台机器进行hash join操作。

7.2.3 Bucket Shuffle Join

    当join列是左表的分桶列,可以采用bucket shuffle join算法。下图中的hash(column) % n 中的n指的是左表的桶数,column代表的是join 列,同时也是分桶列。这样左表数据不移动,右表数据根据分区计算的结果发送到左表扫表的节点就可以完成Join的计算。即只需网络传输一份右表数据就可以了,极大减少了数据的网络传输。

7.2.4 Colocate Join

     两个表在创建的时候就指定了数据分布保持一致,那么当两个表的join key与分桶的key一致时,就会采用colocate join算法。由于两个表的数据分布是一样的,那么hash join操作就相当于在本地,不涉及到任何的数据传输,极大提高查询性能。

  总结上面这 4 种join方式灵活度是从高到低的,它对这个数据分布的要求是越来越严格,但 Join计算的性能也是越来越好的。

7.3 分布式逻辑计划的核心流程

7.3.1  PlanNode

   如果是PlanNode, 自底向上创建PlanFragment。

7.3.2  ScanNode

    如果是ScanNode,则直接创建一个PlanFragment,PlanFragment的RootPlanNode是这个ScanNode。

7.3.3 HashJoinNode

     如果是HashJoinNode,则首先计算下broadcastCost(成本),根据不同的条件判断选择哪种Join算法。

(1)如果使用colocate join,由于join操作都在本地,就不需要拆分。设置HashJoinNode的左子节点为leftFragment的RootPlanNode,右子节点为rightFragment的RootPlanNode,与leftFragment共用一个PlanFragment,删除掉rightFragment。

(2)如果使用bucket shuffle join,需要将右表的数据发送给左表。所以先创建了一个ExchangeNode,设置HashJoinNode的左子节点为leftFragment的RootPlanNode,右子节点为这个ExchangeNode,与leftFragment共用一个PlanFragment,并且指定rightFragment数据发送的目的地为这个ExchangeNode。

(3)如果使用broadcast join,需要将右表的数据发送给左表。所以先创建了一个ExchangeNode,设置HashJoinNode的左子节点为leftFragment的RootPlanNode,右子节点为这个ExchangeNode,与leftFragment共用一个PlanFragment,并且指定rightFragment数据发送的目的地为这个ExchangeNode。

(4)如果使用hash partition join(也就是shuffle joun),左表和右边的数据都要切分,需要将左右节点都拆分出去,分别创建left ExchangeNode, right ExchangeNode,HashJoinNode指定左右节点为left ExchangeNode和 right ExchangeNode。单独创建一个PlanFragment,指定RootPlanNode为这个HashJoinNode。最后指定leftFragment, rightFragment的数据发送目的地为left ExchangeNode, right ExchangeNode。

八、Schedule阶段

  该阶段是根据分布式逻辑计划,创建分布式物理计划。主要解决以下问题:

  • 哪个 BE 执行哪个 PlanFragment

  • 每个Tablet选择哪个副本去查询

  • 如何进行多实例并发

 创建分布式物理计划的核心流程有:

8.1  prepare阶段

     给每个PlanFragment创建一个FragmentExecParams结构,用来表示PlanFragment执行时所需的所有参数;如果一个PlanFragment包含有DataSinkNode,则找到数据发送的目的PlanFragment,然后指定目的PlanFragment的FragmentExecParams的输入为该PlanFragment的FragmentExecParams。

8.2 computeScanRangeAssignment阶段

    对fragment合理分配,尽可能保证每个BE节点的请求都是平均,针对不同类型的join进行不同的处理。

  •  computeScanRangeAssignmentByColocate

      针对colocate join 进行处理,由于Join得两个表桶中的数据分布是一样的,他们是基于桶的join操作,所以在这里确定每个桶选择哪个host。在给host分配桶的时候,尽量保证每个host分配到的桶基本平均。

  • computeScanRangeAssignmentByBucket

      对bucket shuffle join进行处理,也只是基于桶的操作,所以在这里是确定每个桶选择哪个host。在给host分配桶时,同样需要尽量保证每个host分配到的桶基本平均。

  • computeScanRangeAssignmentByScheduler

      针对其他类型的join进行处理。确定每个scanNode读取tablet哪个副本。一个scanNode会读取多个tablet,每个tablet有多个副本。为了使sca操作尽可能的分散到多台机器上去,提高并发性能,减少IO压力,Doris 采用了Round-Robin算法,使tablet的扫描尽可能分散到多台机器上去。例如100个tablet需要扫描,每个tablet有3个副本,假设集群有10台机器,在分配时,保障每台机器扫10个tablet。

8.3 computeFragmentExecParams阶段

      处理Fragment执行参数,这个阶段解决PlanFragment下发到哪个BE上执行, 以及如何处理实例并发问题。

8.4  create result receiver阶段

      result receiver是查询完成后,最终数据需要输出的地方。

8.5  to thrift阶段

     根据所有PlanFragment创建的rpc请求下发到BE端执行,一个完整的SQL解析过程完成了。

综上所述:

九、总结

    本篇文章介绍了sql解析的通用流程:词法分析,语法分析,生成逻辑计划,生成物理计划。从总体上阐述了Doris在sql解析这块的总体架构,从代码和算法层面上解析Parse, Analyze, SinglePlan, DistributedPlan, Schedule五步骤的内容。

    Doris遵守了sql解析的常用方法,根据底层存储架构,以及分布式的特点,在sql解析这块进行了大量的优化,实现了最大化的计算并行度、最小化的数据网络传输,最大化减少需扫描的数据量,给sql执行层面减少了很多负担。

    补充:Hive SQL编译成MapReduce任务的过程 见文章:

(02)Hive SQL编译成MapReduce任务的过程-CSDN博客文章浏览阅读1.4k次,点赞30次,收藏23次。Hive SQL编译成MapReduce的过程https://blog.csdn.net/SHWAITME/article/details/136103206?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170813605316800182123993%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=170813605316800182123993&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-136103206-null-null.nonecase&utm_term=mapreduce&spm=1018.2226.3001.4450

 参考文章:

【Doris全面解析】Doris SQL 原理解析

聊聊分布式 SQL 数据库Doris(五)-腾讯云开发者社区-腾讯云

https://blog.csdn.net/qq_34635236/article/details/128114948?ops_request_misc=&request_id=&biz_id=102&utm_term=doris%20sql%20%E6%BA%90%E7%A0%81&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-128114948.142%5Ev99%5Epc_search_result_base6&spm=1018.2226.3001.4187

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/687342.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL-Labs靶场“11-15”关通关教程

君衍. 一、十一关 基于POST单引号字符型注入1、源码分析2、联合查询注入3、报错注入 二、十二关 基于POST双引号字符型注入1、源码分析2、联合查询注入3、报错注入 三、十三关 基于POST单引号报错注入变形1、源码分析2、报错注入 四、十四关 基于POST双引号报错注入1、源码分析…

代码随想录day24--回溯的应用3

LeetCode93.修复IP地址 题目描述: 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 . 分隔。 例如:"0.1.2.201" 和 "192.168.1.1" 是…

使用八叉树模拟水和烟雾 Simulating Water and Smoke with an Octree Data Structure 论文阅读笔记

原文: Losasso, Frank, Frdric Gibou, and Ron Fedkiw. “Simulating water and smoke with an octree data structure.” Acm siggraph 2004 papers. 2004. 457-462. 引言 这篇文章扩展了 [Popinet 2003] 的工作,拓展到表面自由流,并且使…

Oracle 基础入门指南

一、什么是Oracle? Oracle是一款由美国Oracle公司开发的关系型数据库管理系统。它支持SQL查询语言,并提供了丰富的功能和工具,用于管理大规模数据存储、处理和访问。Oracle被广泛应用于企业级应用中,包括金融、电信、零售等各行各…

第12章 反射

12.1 反射概述 Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以得到任意一个对象所属的类的信息,可以调用任意一个类的成员变量和方法,可以获取任意一个对象的属性和方法…

js---webAPI

01 声明变量 js组成: DOM:操作网页内容的,开发页面内容特效和实现用户交互 BOM: DOM树:将 HTML 文档以树状结构直观的表现出来,我们称之为文档树或 DOM 树 文档树直观的体现了标签与标签之间的关系 CSS获取元素的方法 document.querySele…

精品springboot基于大数据的电脑主机硬件选购助手-可视化大屏

《[含文档PPT源码等]精品基于springboot基于大数据的电脑主机硬件选购助手[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功! 软件开发环境及开发工具: Java——涉及技术: 前端使用技术&a…

Cron表达式选择器

Cron表达式选择器 功能描述 Cron表达式选择器是用于定时任务调度的一种常见工具,通常用于指定任务的执行时间。Cron表达式由一系列时间单位和对应的时间值组成,用于指定任务的执行时间。下面是一个Cron表达式的示例 0 0 12 * * ?这个表达式的含义是每…

电阻器的脉冲浪涌能力?

由于现有需求,许多现代电子电路和设备都会经历瞬态脉冲和浪涌。这反过来又导致需要“设计”瞬态浪涌保护,尤其是在电机控制器等电路中。当电机启动时,此时消耗的电流过大,可能导致电阻器故障。同样,如果电容器用于电机…

【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱13(附带项目源码)

效果演示 文章目录 效果演示前言每次丢弃一个物品源码完结前言 欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中,我们将探索如何用unity制作一个3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机…

MySQL性能分析1

1、查看执行频次 查看当前数据库的INSERT,UPDATE,DELETE,SELECT的访问频次,得到当前数据库是以插入,更新和删除为主还是以查询为主,如果是以插入,更新和删除为主的话,那么优化比重可以轻一点儿。 语法: …

Qt实用技巧:QCustomPlot做北斗GPS显示绝对位置运动轨迹和相对位置运动轨迹图的时,使图按照输入点顺序连曲线

若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/136131310 红胖子网络科技博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

适用于 Windows 的 12 个最佳 PDF 编辑器

PDF文档的普遍存在按理说,PDF文档的可读性和可移植性受到专业文档的青睐。 然而,PDF格式的可食用性是一大缺陷。幸运的是,各种 PDF 编辑工具和软件使 PDF 的编辑变得更加容易,这篇文章旨在帮助我们的读者找到其中最好的工具和软件…

CSS的注释:以“ /* ”开头,以“ */ ”结尾

CSS的注释:以“ /* ”开头,以“*/”结尾 CSS的注释: 以“ /* ”开头,以“ */ ”结尾 在CSS中,注释是一种非常重要的工具,它们可以帮助开发者记录代码的功能、用法或其他重要信息。这些信息对于理解代码、维护代码以及与他人合作都…

JS进阶——垃圾回收机制以及算法

版权声明 本文章来源于B站上的某马课程,由本人整理,仅供学习交流使用。如涉及侵权问题,请立即与本人联系,本人将积极配合删除相关内容。感谢理解和支持,本人致力于维护原创作品的权益,共同营造一个尊重知识…

IDM6.42.3下载器(Internet Download Manager)俄罗斯大神版,

IDM下载器(Internet Download Manager)俄罗斯大神版,目前最新版是 6.42.3。 Internet Download Manager(简称:IDM)是一款来自国外的非常优秀网络资源高速下载及管理工具,该软件同时是一款收费共…

计算机毕业设计SSM基于的高校学习资源共享系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: vue mybatis Maven mysql5.7或8.0等等组成,B…

电子元器件基础6---三极管

了解了二极管后,接下来就是三极管了。二极管是一个PN结,而三极管是两个PN结构成。 一、三极管概念 三极管,全称应为半导体三极管,也称双极型晶体管、晶体三极管,是一种控制电流的半导体器件。其作用是把微弱信号放大成幅度值较大的电信号,也用作无触点开关。 三极管是半…

php数据类型以及运算符、判断条件

php数据类型以及运算符 1. php数据类型2. 使用举例3. 运算符4. 判断条件if else elseif 1. php数据类型 包括 String(字符串)、Integer(整型)、Float(浮点型)、Boolean(布尔型)、Array(数组)、Object(对象)、NULL(空值) 2. 使用举例 1.字符串 2.整型 3.浮点型 4.布尔型 5.数组…

出境游确实在恢复

新加坡开放中国大陆游客免签,我坦白承认,这是我之前未曾预料的。 那么春节期间,朋友圈里见证了市中心的蜂拥盛景,很多在坡多年的朋友说,在新加坡多年,从未见过如此拥挤的人群,甚至非常担心会出现…