当前位置: 首页 > news >正文

KaiwuDB 内核解析 - SQL 查询的生命周期

 一、概述

KaiwuDB 内核解析系列共分上下两部分,本文是该系列的第一部分,主要涵盖了网络协议到 SQL 执行器,解释 KaiwuDB 如何执行 SQL 查询,包括系统各个组件的执行路径(网络协议、SQL 会话管理、解析器、执行计划及优化、执行器、KV 引擎、事务管理等),目的是为各个组件的结构及其之间的关系提供一个高层次的统一视图。

下图是 KaiwuDB SQL 查询执行概览。左侧是 gateway 节点,负责接收 SQL Client 的 SQL 查询,生成查询计划(逻辑计划和物理计划),构造分布式执行引擎需要的 FlowSpec 并发送到被查询数据所在的节点。每个节点会根据接收到的 FlowSpec 构造物理计划中的算子并执行,然后把数据通过网络返回到 gateway 节点。接下来我们就详细讨论一下各个组件是如何工作的。

二、PostgreSQL Wire Protocol

SQL 查询通过 Postgres Wire 协议发送到 KaiwuDB(使用 Postgres 协议是为了与现有的客户端驱动和应用程序兼容)。这个组件实现了与 Postgres wire 协议相关的功能接口。用户连接后会首先进行鉴权,鉴权通过后,就会初始化一个循环,不断地读取 SQL 语句、执行并返回结果(通过封装 golang 的 net.Conn)。

这个协议是面向消息的(PostgreSQL 消息类型,见执行器部分):在当前连接的生命周期内,会读取一个或多个包含 SQL 语句的消息,并将其传递给 SQL 执行器执行;一旦 SQL 语句执行完毕并生成结果,就会将其序列化并返回给客户端。

PostgreSQL Wire Protocol Server 是在 KaiwuDB 启动的同时初始化的。详细的初始化流程如下图所示。首先,KaiwuDB 的 start 命令会通过 server.Start 方法调用 startServeSQL 来初始化 ServConn。ServConn 负责解析 SQL 客户端的请求、检查连接的安全性并处理连接参数,然后调用 pgServer.ServConn 方法来处理 SQL Statement。

三、SQL 执行器

KaiwuDB 使用一个端口同时处理 pg/http/grpc 三种协议。在 start 阶段,KaiwuDB 实例化 pgServer 来处理 Postgres wire 协议的请求。pgServer 会实例化 KaiwuDB 的 SQL 执行器处理用户查询。

SQL 执行器会作为生产者( Producer),持续读取用户输入并调用 parser 解析 SQL 为 statement,解析的结果会保存到 Statement buffer(StmtBuf)中。同时,还会创建一个 go routine 作为消费者(Consumer),按序处理 StmtBuf 中的 SQL statements。

SQL 执行器的具体处理流程如下图所示。首先,它会通过 serverImpl 调用 processCommandsAsync 创建一个新的 goroutine,来认证客户端连接和处理 Statement buffer(StmtBuf)中的命令(上文提到的消费者)。

其返回值是一个用来标示 goroutine 是否结束的 channel。需要注意的是,这个 channel 中的任何错误信息都会被忽略,因为期间发生的任何错误的详细信息已经通知了 SQL 客户端。processCommandsAsync 还会进行鉴权工作,如果鉴权失败,这个 goroutine 就会结束,并且会调用 cancelConn 关闭整个连接。

接下来,serverImpl 会初始化一个 for loop 来接收 SQL 客户端的输入,直到连接关闭或者发生错误。此处的 for loop 是作为生产者,首先验证 SQL Client 的权限,通过后,会根据客户端发送的消息类型调用不同的方法。

消息类型定义请参考>>https://www.postgresql.org/docs/9.4/protocol-message-formats.html

下面的章节会以 handleSimpleQuery 方法为例,来说明 SQL 执行器处理 SQL 的过程。

1. SQL 接收与解析

handleSimpleQuery 的目的是用来处理简单 SQL。首先,它会从 PostgreSQL Wire Protocol 的缓存中读取一个字符串。如果读取成功,这个字符串就会发送给 KaiwuDB 的  SQL parser(SQL 解析器)。

KaiwuDB 的解析器最初复制于 PostgresSQL,随着支持更多的 SQL 语法而逐渐增强。SQL 解析器的输出为 AST(抽象语法树)数组,每个 SQL 语句一个。AST 的节点是由 pkg/sql/sem/tree 中定义的 tree.Statement 结构组成:

Go
type Statement interface {fmt.StringerNodeFormatterStatementType() StatementType// StatementTag is a short string identifying the type of statement// (usually a single verb). This is different than the Stringer output,// which is the actual statement (including args).// TODO(dt): Currently tags are always pg-compatible in the future it// might make sense to pass a tag format specifier.StatementTag() string
}

KaiwuDB 实现了使用 tree.Statement 的子类抽象了 SQL 语句的各个子句。比如,tree.SelectClause 结构抽象了 SQL 中的 SELECT 子句,包括 SELECT 的 From 和 Where 子句。同时,AST 树中的许多部分会包含一个或多个 tree.Expr 结构,用来表示诸如 l_extendedprice * (1 - l_discount)这样的算术表达式。

Go
type SelectClause struct {Distinct    boolDistinctOn  DistinctOnExprs       SelectExprsFrom        FromWhere       *WhereGroupBy     GroupByHaving      *WhereWindow      WindowTableSelect bool
}type BinaryExpr struct {Operator    BinaryOperatorLeft, Right ExprtypeAnnotationfn *BinOp
}

SQL 解析成功后,会被添加到 Statement bufer 中等待执行器处理。

下面我们以 TPCH 中的 Q7 为例,展示一下 KaiwuDB 中 AST 的结构。

TPCH 的 Q7 是用来查询两个特定国家之间(此处为法国和德国)在某段时间内(1995-01-01 到 1996-12-31)的货物运输总价值。

SQL
SELECTsupp_nation,cust_nation,l_year, sum(volume) AS revenue
FROM (SELECTn1.n_name AS supp_nation,n2.n_name AS cust_nation,extract(year FROM l_shipdate) AS l_year,l_extendedprice * (1 - l_discount) AS volumeFROMsupplier,lineitem,orders,customer,nation n1,nation n2WHEREs_suppkey = l_suppkeyAND o_orderkey = l_orderkeyAND c_custkey = o_custkeyAND s_nationkey = n1.n_nationkeyAND c_nationkey = n2.n_nationkeyAND ((n1.n_name = 'FRANCE' AND n2.n_name = 'GERMANY')or (n1.n_name = 'GERMANY' AND n2.n_name = 'FRANCE'))AND l_shipdate BETWEEN DATE '1995-01-01' AND DATE '1996-12-31') AS shipping
GROUP BYsupp_nation,cust_nation,l_year
ORDER BYsupp_nation,cust_nation,l_year;

下图即为 KaiwuDB 中 TPCH Q7 的 AST(为了方便展示做了简化处理)。每个节点中的白色部分代表空值(nil),表示当前节点不包含该结构;紫色部分代表该结构可以展开,即指向下个子节点;绿色部分代表叶节点。

因为 Q7 是 SELECT 语句,其根节点是 tree.Statement 的子类 tree.Select。Q7 中每个 Statement 都被抽象为一个具体的节点,比如 ORDER BY 被表示为 tree.OrderBy,WHERE 子句被表示为 tree.Where 等。

2. SQL 语句执行

上文提到,SQL 执行器的消费者 goroutine 会不断地从 Statement buffer 中读取 SQL 的 AST 并执行,这个功能是通过 sqlServer.ServeConn 调用 connExecutor 的 execCmd 来实现的,其主要流程见下图。

execCmd 方法会不断地读取 stmtBuf 中的内容并执行。每个 SQL 客户端连接初始化的时候,KaiwuDB 都会初始化一个用来执行 SQL 的有限状态机(FSM),它有 5 种状态:

  • stateNoTxn – 用来处理 BEGIN 语句或隐式事务(为其开启一个新的事务)

  • stateOpen – 用来执行普通的 SQL 语句

  • stateAborted – 用来处理 ROLLBACK 语句

  • stateCommitWait – 用来处理 COMMIT 语句

  • stateInternalError – 用来处理各种错误,比如 eventNonRetriableErr, stateInternalError 等

stmtBuf 的 SQL 指令被添加到状态机后,会根据其类型分别处理。普通 SQL 被定义为 ExecStmt 类型,会通过调用 connExecutor 的 execStmt 方法运行,如上图中所示。

execStmt 方法会首先判断当前状态机的状态,如果是 BEGIN 语句,则会执行 connExecutor 的 execStmtInNoTxnState 方法创建新的事务;如果是普通的 SQL 则会调用 connExecutor 的 execStmtInOpenState 运行。

下图为 execStmtInNoTxnState 创建新事物的过程。如果当前语句是 BEGIN,则会开始一个新的事物。如果是 tree.CommitTransaction, tree.ReleaseSavepoint, tree.RollbackTransaction, tree.SetTransaction 或 tree.Savepoint 中的任何一个,则会报错;其它情况(即普通的 SQL 语句),则会转换状态机的状态到 stateOpen 并创建一个隐式事务。

事务创建成功并且状态机的状态转换为 stateOpen 后,SQL 就会进入执行阶段,这部分内容会在后续文章中详细介绍。

相关文章:

KaiwuDB 内核解析 - SQL 查询的生命周期

一、概述 KaiwuDB 内核解析系列共分上下两部分,本文是该系列的第一部分,主要涵盖了网络协议到 SQL 执行器,解释 KaiwuDB 如何执行 SQL 查询,包括系统各个组件的执行路径(网络协议、SQL 会话管理、解析器、执行计划及优…...

2023.11.03 homework

小学4年级数学 1 2 3 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 19…...

ssm在线互助答疑系统-计算机毕设 附源码 20862

ssm在线互助答疑系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流,人类发展的历史正进入一个新时代。在现实运用中&#…...

MySQL中如何书写update避免锁表

1. 什么是MySQL锁表? MySQL锁表是指在对某个数据表进行读写操作时,为了保证数据的一致性和完整性,系统会对该数据表进行锁定,防止其他用户对该表进行操作。 2. 为什么会出现锁表? 当多个用户同时对同一个数据表进行…...

Mysql库操作

一:库的操作 1:创建数据库 mysql> create database test1; Query OK, 1 row affected (0.00 sec)mysql> create database test2 charsetutf8;create database test2 character utf8;Query OK, 1 row affected (0.00 sec)mysql> create databa…...

C#中LINQtoSQL只能在.NetFramework下使用,不能在.net 下使用

目录 一、在net7.0下无法实现LINQtoSQL 1.VS上建立数据库连接 2.VS上创建LINQtoSQL 二、在.NetFramework4.8下成功实现LINQtoSQL 1.VS上建立数据库连接 2.VS上创建LINQtoSQL 三、结论 四、理由 本文是个人观点,因为我百般努力在.net7.0下无法实现LINQtoSQL的…...

Nacos 的底层实现原理 注册中心的两种调用方式

目录 1. Nacos 的底层实现原理 1.1 配置中心自动刷新实现原理 1.2 注册中心底层实现原理 2. Nacos 注册中心的两种调用方式 2.1 RestTemplate Spring Cloud LoadBalancer 的调用方式 2.2 使用 OpenFeign Spring Cloud LoadBalancer 1. Nacos 的底层实现原理 1.1 配置中心…...

视频编码格式和文件格式(多媒体容器格式)的关系

视频编码格式和文件格式是两个不同的概念。 视频编码格式指的是将视频信号转换为数字信号时所采用的压缩算法标准。它决定了如何将原始视频数据压缩为较小的文件大小,以及如何解码回原始视频数据。目前常见的视频编码格式有 H.264、H.265、VP9 等。 文件格式则是指…...

RHCSA --- 第二天

一、查看IP地址 [rootlocalhost ~] ip ad 对应四张网卡 第一张&#xff1a;环回网卡&#xff08;用于测试&#xff09; 第二张&#xff08;主要&#xff09;&#xff1a;以太网网卡&#xff08;ens160&#xff09; 2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP>…...

作为一个初学者,入门大模型其实没那么难

在生成式 AI 盛行的当下&#xff0c;你是否被这种技术所折服&#xff0c;例如输入一段简简单单的文字&#xff0c;转眼之间&#xff0c;一幅精美的图片&#xff0c;又或者是文笔流畅的文字就展现在你的面前。 相信很多人有这种想法&#xff0c;认为生成式 AI 深不可测&#xf…...

【QT】基本的绘图操作和高级绘图

基本绘图 新建项目 重新绘图事件 画基本图形 #include "widget.h" #include "ui_widget.h" #include <QPainter>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }/…...

layer.open再次渲染html,子页面调用在父页面打开弹出层,渲染html

使用的版本 layui-v2.5.6是在父页面弹出层&#xff0c;显示&#xff1b;调用的是父页面的layer.open(); 父页面&#xff1a; <link href"/layui/css/layui.css" rel"stylesheet" /> <script src"/layui/layui.all.js"></script…...

【Apache Flink】Flink DataStream API的基本使用

Flink DataStream API的基本使用 文章目录 前言1. 基本使用方法2. 核心示例代码3. 完成工程代码pom.xmlWordCountExample测试验证 4. Stream 执行环境5. 参考文档 前言 Flink DataStream API主要用于处理无界和有界数据流 。 无界数据流是一个持续生成数据的数据源&#xff0…...

民安:专业在线教育平台客户满意度调查的引领者

在当今的在线教育市场中&#xff0c;客户满意度已成为衡量平台竞争力的关键因素。为了准确了解客户的需求和反馈&#xff0c;某在线教育企业委托民安智库&#xff08;专业市场调查公司&#xff09;对其进行全面的客户满意度调查。 此次调查旨在了解客户对在线教育平台的服务质…...

浅谈新能源汽车充电桩的选型与安装

叶根胜 安科瑞电气股份有限公司 上海嘉定201801 摘要&#xff1a;电动汽车的大力发展和推广是国家为应对日益突出的燃油供需矛盾和环境污染&#xff0c;加强生态环境保护和治理而开发新能源和清洁能源的措施之一&#xff0c;加快了电动汽车的发展。如今&#xff0c;电动汽车已…...

FFmpeg系列索引

第一章 初识FFmpeg https://blog.csdn.net/huantianxidi/article/details/134130159 第二章 ffplay是什么 https://blog.csdn.net/huantianxidi/article/details/134151043...

AWS组件使用

kafka或kinesis 做数据收集 S3redshift 做数仓 EMR做计算 RDS做数据市场 AWS Glue / AWS Data Pipeline 做数据集成 这些组件配合起来&#xff0c;几乎可以做各种方式的数据分析 kinesis还是比较推荐&#xff0c;延迟时间可以配置的算是实时的&#xff0c;而且功能会多一点&am…...

DALLE 3技术分析 - 训练方式/模型结构

DALLE 3技术分析 - 训练方式/模型结构 1. 引言: 从 DALLE 3 开发者技术轨迹中&#xff0c;以及模型的演示视频&#xff0c;我们可以推导 DALLE 3 模型的某些架构信息。 2. DALLE 2 的评价: DALLE 2 的性能不佳&#xff0c;主要归因于 CLIP 模型的限制。 CLIP 在为后续的 diffus…...

Go的自定义错误

在上一篇教程中&#xff0c;我们了解了 Go 中的错误表示以及如何处理标准库中的错误。我们还学习了如何从错误中提取更多信息。 本教程介绍如何创建我们自己的自定义错误&#xff0c;我们可以在函数和包中使用这些错误。我们还将使用标准库所采用的相同技术来提供有关自定义错…...

SpringBoot集成Dubbo

在SpringMVC中Dubbo的使用https://tiantian.blog.csdn.net/article/details/134194696?spm1001.2014.3001.5502 阿里巴巴提供了Dubbo集成SpringBoot开源项目。(这个.....) 地址GitHub https://github.com/apache/dubbo-spring-boot-project 查看入门教程 反正是pilipala一大…...

利用shp文件构建mask【MATLAB和ARCGIS】两种方法

1 ARCGIS &#xff08;推荐&#xff01;&#xff01;&#xff01;-速度很快&#xff09; 利用Polygon to Raster 注意&#xff1a;由于我们想要的mask有效值是1&#xff0c;在进行转换的时候&#xff0c;注意设置转换字段【Value field】 【Value field】通过编辑shp文件属性表…...

Luminar Neo Mac/Windows中文版:引领AI图像编辑的革命性时代

Luminar Neo运用先进的AI技术&#xff0c;能够自动化地完成许多繁琐的编辑任务&#xff0c;如色彩校正、噪点消除、人脸识别等。这不仅大大提高了工作效率&#xff0c;同时也降低了对专业知识和技能的要求。无论你是专业摄影师&#xff0c;还是摄影爱好者&#xff0c;甚至是一个…...

远程设备常用工具:向日葵、Todesk

其实按理说远程工具例如向日葵、Todesk如果是计算机专业、计算机从业者是必须知道的一个东西&#xff0c;但是在大学期间身边知道的人是少之又少的。 向日葵、Todesk工具的优势&#xff1a;方便、快捷、速度快等等我就不过多阐述了 PS:现在我就是在学校用远程写这篇 很多时候…...

JAVA七种常见排序算法

前言&#xff1a; 排序算法在计算机科学中扮演着至关重要的角色&#xff0c;它们用于将无序数据变为有序数据&#xff0c;以便更有效地检索和处理信息。不同的排序算法适用于不同的情况&#xff0c;因此了解它们的工作原理和性能特点对于选择正确的算法至关重要。本文提供的Jav…...

高质量绝世玄幻小说,情节引人入胜,一读成痴的绝佳选择

《我有一个修仙世界》 在这个高科技后修仙时代&#xff0c;主角拥有资源丰富的原始修仙世界。他需要不断地探索、发掘、修炼&#xff0c;才能成为真正的修仙者。这是一本充满想象力和创意的小说。 《长生武道&#xff1a;从五禽养生拳开始》 林轩修炼养生类功法&#xff0c;通过…...

Flask三种添加路由的方法

Flask 是一个流行的 Python Web 框架&#xff0c;它提供了多种方法来添加路由。路由是将 URL 映射到特定函数的过程&#xff0c;它是构建 Web 应用程序的基础。本文将介绍 Flask 中几种常用的路由添加方法&#xff0c;并附带代码示例。 方法一&#xff1a;使用装饰器 from flas…...

基于layui的select选择框修改为多选框

layui-xm-select 的功能强大&#xff0c;可多选、可下拉树、下拉日期多选、下拉折叠面板、下拉穿梭框、级联模式。 首先在引用layui css和js 的基础上&#xff0c;再引用js&#xff1a;layui-xm-select layui-xm-select点击下载地址 基本使用 第一步: 下载 第二步: 引入 layu…...

【技术分享】RK356X Android 使用 libgpiod 测试gpio

前言 libgpiod 是用于与 Linux GPIO 字符设备交互的 C 库和工具库&#xff1b;此项目包含六种命令行工具&#xff08;gpiodetect、gpioinfo、gpioset、gpioget、gpiomon&#xff09;&#xff0c;使用这些工具可以在命令行设置和获取GPIO的状态信息&#xff1b;在程序开发中也可…...

代碼隨想錄算法訓練營|第五十九天|647. 回文子串、7516.最长回文子序列、动态规划总结篇。刷题心得(c++)

目录 讀題 647. 回文子串 看完代码随想录之后的想法 516.最长回文子序列 看完代码随想录之后的想法 647. 回文子串 - 實作 思路 動態規劃思路 雙指針思路 Code 動態規劃思路 雙指針思路 516.最长回文子序列 - 實作 思路 Code 动态规划 - 總結 動態規劃基礎 動…...

Qt封装的Halcon显示控件,支持ROI绘制

前言 目前机器视觉ROI交互控件在C#上做的比较多&#xff0c;而Qt上做的比较少&#xff0c;根据作者 VSQtHalcon——显示图片&#xff0c;实现鼠标缩放、移动图片的文章&#xff0c;我在显示和移动控件的基础上&#xff0c;增加了ROI设置功能&#xff0c;并封装成了一个独立的Q…...