DuckDB核心模块揭秘 | 第1期 | 向量化执行引擎之Pipeline
DuckDB核心模块揭秘 | 第1期 | 向量化执行引擎之Pipeline
DuckDB是一款非常火的OLAP嵌入式数据库,性能超级棒。它分为多个组件:解析器、逻辑规划器、优化器、物理规划器、执行器以及事务和存储管理层。其中解析器原语PgSQL的解析器;逻辑规划器包含binder、plan generator,前者解析所有引用的schema中的对象的表达式,将其与列名和类型匹配,后者将binder生成的AST转换成由基本逻辑查询运算符组成的树;优化器产生优化的查询计划;物理规划器将优化的查询计划转换成物理执行计划,即PhysicalOperator树。它的高性能主要得益于它的push-based pipeline向量化执行引擎。本文介绍下它的向量化引擎pipeline生成原理。
1、物理执行计划长什么样?有哪些算子?
physical_plan_generator.cpp中CreatePlan函数将逻辑计划节点转换成物理计划节点,即PhysicalOperator。有哪些算子类型呢?PhysicalOperatorType:
//===--------------------------------------------------------------------===//
// Physical Operator Types
//===--------------------------------------------------------------------===//
enum class PhysicalOperatorType : uint8_t {INVALID,ORDER_BY,LIMIT,STREAMING_LIMIT,LIMIT_PERCENT,TOP_N,WINDOW,UNNEST,UNGROUPED_AGGREGATE,HASH_GROUP_BY,PERFECT_HASH_GROUP_BY,FILTER,PROJECTION,COPY_TO_FILE,BATCH_COPY_TO_FILE,FIXED_BATCH_COPY_TO_FILE,RESERVOIR_SAMPLE,STREAMING_SAMPLE,STREAMING_WINDOW,PIVOT,// -----------------------------// Scans// -----------------------------TABLE_SCAN,DUMMY_SCAN,COLUMN_DATA_SCAN,CHUNK_SCAN,RECURSIVE_CTE_SCAN,CTE_SCAN,DELIM_SCAN,EXPRESSION_SCAN,POSITIONAL_SCAN,// -----------------------------// Joins// -----------------------------BLOCKWISE_NL_JOIN,NESTED_LOOP_JOIN,HASH_JOIN,CROSS_PRODUCT,PIECEWISE_MERGE_JOIN,IE_JOIN,DELIM_JOIN,INDEX_JOIN,POSITIONAL_JOIN,ASOF_JOIN,// -----------------------------// SetOps// -----------------------------UNION,RECURSIVE_CTE,CTE,// -----------------------------// Updates// -----------------------------INSERT,BATCH_INSERT,DELETE_OPERATOR,UPDATE,// -----------------------------// Schema// -----------------------------CREATE_TABLE,CREATE_TABLE_AS,BATCH_CREATE_TABLE_AS,CREATE_INDEX,ALTER,CREATE_SEQUENCE,CREATE_VIEW,CREATE_SCHEMA,CREATE_MACRO,DROP,PRAGMA,TRANSACTION,CREATE_TYPE,ATTACH,DETACH,// -----------------------------// Helpers// -----------------------------EXPLAIN,EXPLAIN_ANALYZE,EMPTY_RESULT,EXECUTE,PREPARE,VACUUM,EXPORT,SET,LOAD,INOUT_FUNCTION,RESULT_COLLECTOR,RESET,EXTENSION
}; 让我们看一个简单inner join的例子:物理执行计划最上头是投影算子PROJECTION,然后其左子树是HASH_JOIN算子,HASH_JOIN两个子算子分别为两个顺序扫描SEQ_SCAN:

基于物理执行计划构建出pipeline,真正执行的是pipeline。
2、物理执行计划如何构建pipeline?
2.1什么是MetaPipeline
MetaPipeline 表示一组都具有相同Sink的Pipeline。Source为输入,Sink为输出,Other Node就是其他节点,将一个物理执行计划树转换成多个pipeline。一个pipeline包含一个source和一个sink以及若干个operators。

pipeline还存在一定的依赖关系,hashjoin节点必须依赖build端的pipeline产生的数据才行,所以就需要MetaPipeline构建多个pipeline依赖关系,最后执行时仅关注pipeline就可以。
以1中的例子介绍pipeline的构建过程:
2.2 Pipeline的构建
1)最开始由Executor::InitializeInteral函数创建一个MetaPipeline。该MetaPipeline的sink为NULL,vector<>pipelines容器创建一个pipeline,该pipeline的sink为NULL。

2)接着调用root_pipeline->Build(*physical_plan)使用上面的MetaPipeline继续构建pipeline
3)physical_plan为RESULT_COLLECTOR,Build会调用对应operator的Buildipelines,即调用PhysicalResultCollector::BuildPipelines,PhysicalResultCollector为PhysicalOperator的子类。
将当前operator即PhysicalResultCollector作为当前pipeline的source,如上图所示。
4)接着在调用CreateChildMetaPipeline创建一个child_meta_pipeline,sink节点为当前节点,即PhysicalResultCollector:并构建出和上一个pipeline的父子关系

代码:

5)紧接着使用child_meta_pipeline继续构建pipeline。下一个算子是PROJECTION:PhysicalProjection,它没有重写基类的BuildPipelines,那么就调用PhysicalOperator的BuildPipelines:

projection不是sink,并且它的子节点不为空,所以在当前pipeline添加一个算子即PhysicalProjection:也就是将PhysicalProjection放到当前pipeline的operators容器中

6)children[0]->BuildPipelines构建当前算子PhysicalProjection子节点的pipeline。此时到了HashJoin,即需要调用PhysicalHashJoin的PhysicalJoin::BuildJoinPipelines继续构建pipeline

首先将HashJoin添加到当前pipeline的operator容器中(因为作为探测端的pipeline);然后保留一份当前MetaPipeline中的所有pipeline到pipelines_so_for后面使用;接着构建build端的MetaPipeline:CreateChildMetaPipeline函数完成:主要是构建一个pipeline,sink为当前PhysicalHashJoin,source为PhysicalTableScan:此时构建的pipeline如下图所示:

7)然后调用op.children[0].BuildPipelines继续build探测端的pipeline,实际上将左表的PhysicalTableScan设置到探测端pipeline的Source中。如上图所示。
8)外连接需要使用步骤6)保存的pipeline,构建一个childpipeline:

即使用Metapipeline2的pipeline再构建一个childpipeline,需要将PhysicalProjection操作符算子也加进去,此时结构如下图所示:

9)接着会添加依赖,都是在CreateChildPipeline函数中完成。对于当前的metapipeline,即MetaPipeline2它有两个pipeline:pipeline[0]:probe端;pipeline[1]:child pipeline。首先将当前pipeline(pipeline[0])放到dependencies[child_pipeline]中;然后调用AddDependenciesFrom(child_pipeline, last_pipeline, false)继续添加依赖关系,从last_pipeline开始继续向dependencies中添加。
例如,当前metapipeline中有n个pipeline,下面pipeline[1]为起使pipeline,pipeline[m]为dependant,那么会将中间所有的pipeline都添加到dependant依赖数组里面。
pipelines[0]
....
pipelines[s] ---> start
.....
pipelines[m] ---> dependantpipelines[n-1] 结构:unordered_map<Pipeline *, vector<Pipeline *>> dependencies;完成依赖后:
pipelines[m] : [pipelines[s]......pipelines[m-1]]
由于这里的s=0;m=1所以依赖关系为:pipelines[1] : [ pipelines[0] ],其中pipeline[1]就是child_pipeline。如此:child_pipeline : [probe pipeline],表示probe pipeline依赖child_pipeline.
10)返回到1),此时进入root_pipeline->Ready()

以8)的metapipeline2中的pipeline[0]为例,反转前:

反转后:

11)总结:8)中为所有Metapipeline和pipeline:
第一个Metapipeline:
{pipelines[1], children[1]}
第二个Metapipeline:Children Metapipeline:
{pipelines[2], children[1]}
第三个Metapipeline:children metapipeline:
{pipelines[1], children[0]}
注意:表示的是数组大小
12)最后再次回到1)Executor::InitializeInternal函数,会从root_pipeline(他是metapipeline),递归调用所有的metapipeline的pipelines数组,将pipeline汇总到root_pipelines中:
root_pipeline->GetPipelines(root_pipelines, false);
//vector<shared_ptr<Pipeline>> root_pipelines; 这就是pipeline的一个生成过程,下期介绍这些pipeline是如何调度的
相关文章:
DuckDB核心模块揭秘 | 第1期 | 向量化执行引擎之Pipeline
DuckDB核心模块揭秘 | 第1期 | 向量化执行引擎之Pipeline DuckDB是一款非常火的OLAP嵌入式数据库,性能超级棒。它分为多个组件:解析器、逻辑规划器、优化器、物理规划器、执行器以及事务和存储管理层。其中解析器原语PgSQL的解析器;逻辑规划器…...
Vue如何让用户通过a链接点击下载一个excel文档
在Vue中,通过<a>标签让用户点击下载Excel文档,通常需要确保服务器支持直接下载该文件,并且你有一个可以直接访问该文件的URL。以下是一些步骤和示例,展示如何在Vue应用中实现这一功能。 1. 服务器端支持 首先,…...
美摄科技企业级视频拍摄与编辑SDK解决方案
在数字化浪潮汹涌的今天,视频已成为企业传递信息、塑造品牌、连接用户不可或缺的强大媒介。为了帮助企业轻松驾驭这一视觉盛宴的制作过程,美摄科技凭借其在影视级非编技术领域的深厚积累,推出了面向企业的专业视频拍摄与编辑SDK解决方案&…...
MySQL:增删改查、临时表、授权相关示例
目录 概念 数据完整性 主键 数据类型 精确数字 近似数字 字符串 二进制字符串 日期和时间 MySQL常用语句示例 SQL结构化查询语言 显示所有数据库 显示所有表 查看指定表的结构 查询指定表的所有列 创建一个数据库 创建表和列 插入数据记录 查询数据记录 修…...
初识git工具~~上传代码到gitee仓库的方法
目录 1.背景~~其安装 2.gitee介绍 2.1新建仓库 2.2进行相关配置 3.拉取仓库 4.服务器操作 4.1克隆操作 4.2查看本地仓库 4.3代码拖到本地仓库 4.4关于git三板斧介绍 4.4.1add操作 4.4.2commit操作 4.4.3push操作 5.一些其他说明 5.1.ignore说明 5.2git log命令 …...
Redis知识点总价
1 redis的数据结构 2 redis的线程模型 1) Redis 采用单线程为什么还这么快 之所以 Redis 采用单线程(网络 I/O 和执行命令)那么快,有如下几个原因: Redis 的大部分操作都在内存中完成,并且采用了高效的…...
大语言模型-GPT-Generative Pre-Training
一、背景信息: GPT是2018 年 6 月由OpenAI 提出的预训练语言模型。 GPT可以应用于复杂的NLP任务中,例如文章生成,代码生成,机器翻译,问答对话等。 GPT也采用两阶段的训练过程,第一阶段是无监督的方式来预训…...
mybatis批量插入、mybatis-plus批量插入、mybatis实现insertList、mybatis自定义实现批量插入
文章目录 一、mybatis新增批量插入1.1、引入依赖1.2、自定义通用批量插入Mapper1.3、把通用方法注册到mybatisplus注入器中1.4、实现InsertList类1.5、需要批量插入的dao层继承批量插入Mapper 二、可能遇到的问题2.1、Invalid bound statement 众所周知,mybatisplus…...
Springboot项目的行为验证码AJ-Captcha(源码解读)
目录 前言1. 复用验证码2. 源码解读2.1 先走DefaultCaptchaServiceImpl类2.2 核心ClickWordCaptchaServiceImpl类 3. 具体使用 前言 对于Java的基本知识推荐阅读: java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)【Java项目…...
【初阶数据结构篇】时间(空间)复杂度
文章目录 算法复杂度时间复杂度1. 定义2. 表示方法3. 常见时间复杂度4.案例计算分析冒泡排序二分查找斐波那契数列(递归法)斐波那契数列(迭代法) 空间复杂度案例分析冒泡排序斐波那契数列(递归法)斐波那契数…...
C# 设计模式分类
栏目总目录 1. 创建型模式(Creational Patterns) 创建型模式主要关注对象的创建过程,包括如何实例化对象,并隐藏实例化的细节。 单例模式(Singleton):确保一个类只有一个实例,并提…...
前端模块化CommonJS、AMD、CMD、ES6
在前端开发中,模块化是一种重要的代码组织方式,它有助于将复杂的代码拆分成可管理的小块,提高代码的可维护性和可重用性。CommonJS、AMD(异步模块定义)和CMD(通用模块定义)是三种不同的模块规范…...
论文阅读:(DETR)End-to-End Object Detection with Transformers
论文阅读:(DETR)End-to-End Object Detection with Transformers 参考解读: 论文翻译:End-to-End Object Detection with Transformers(DETR)[已完结] - 怪盗kid的文章 - 知乎 指示函数&…...
react中路由跳转以及路由传参
一、路由跳转 1.安装插件 npm install react-router-dom 2.路由配置 路由配置:react中简单的配置路由-CSDN博客 3.实现代码 // src/page/index/index.js// 引入 import { Link, useNavigate } from "react-router-dom";function IndexPage() {const …...
C++ STL set_symmetric_difference
一:功能 给定两个集合A,B;求出两个集合的对称差(只属于其中一个集合,而不属于另一个集合的元素),即去除那些同时在A,B中出现的元素。 二:用法 #include <vector>…...
postman请求响应加解密
部分接口,需要请求加密后,在发动到后端。同时后端返回的响应内容,也是经过了加密。此时,我们先和开发获取到对应的【密钥】,然后在postman的预执行、后执行加入js脚本对明文请求进行加密,然后在发送请求&am…...
数据集,批量更新分类数值OR批量删除分类行数据
数据集批量更新分类OR删除分类行数据 import osdef remove_class_from_file(file_path, class_to_remove):"""从YOLO格式的标注文件中删除指定类别的行记录,并去除空行。:param file_path: YOLO标注文件路径:param class_to_remove: 需要删除的类别…...
一款功能强大的视频编辑软件会声会影2023
会声会影2023是一款功能强大的视频编辑软件,由加拿大Corel公司制作,正版英文名称为Corel VideoStudio。它具备图像抓取和编修功能,可以处理和转换多种视频格式,如MV、DV、V8、TV和实时记录抓取画面文件。会声会影提供了…...
政安晨【零基础玩转各类开源AI项目】基于Ubuntu系统部署LivePortrait :通过缝合和重定向控制实现高效的肖像动画制作
目录 项目论文介绍 论文中实际开展的工作 非扩散性的肖像动画 基于扩散的肖像动画 方法论 基于Ubuntu的部署实践开始 1. 克隆代码并准备环境 2. 下载预训练权重 3. 推理 快速上手 驱动视频自动裁剪 运动模板制作 4. Gradio 界面 5. 推理速度评估 社区资源 政安…...
在Spring项目中使用Maven和BCrypt来实现修改密码功能
简介 在数字时代,信息安全的重要性不言而喻,尤其当涉及到个人隐私和账户安全时。每天,无数的用户登录各种在线服务,从社交媒体到银行账户,再到电子邮件和云存储服务。这些服务的背后,是复杂的系统架构&am…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
