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.Stringer
  NodeFormatter
  StatementType() 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    bool
  DistinctOn  DistinctOn
  Exprs       SelectExprs
  From        From
  Where       *Where
  GroupBy     GroupBy
  Having      *Where
  Window      Window
  TableSelect bool
}

type BinaryExpr struct {
  Operator    BinaryOperator
  Left, Right Expr

  typeAnnotation
  fn *BinOp
}

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

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

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

SQL
SELECT
    supp_nation,
    cust_nation,
    l_year, sum(volume) AS revenue
FROM (
    SELECT
        n1.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 volume
    FROM
        supplier,
        lineitem,
        orders,
        customer,
        nation n1,
        nation n2
    WHERE
        s_suppkey = l_suppkey
        AND o_orderkey = l_orderkey
        AND c_custkey = o_custkey
        AND s_nationkey = n1.n_nationkey
        AND c_nationkey = n2.n_nationkey
        AND (
            (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 BY
    supp_nation,
    cust_nation,
    l_year
ORDER BY
    supp_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 就会进入执行阶段,这部分内容会在后续文章中详细介绍。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ucos_conf、ucos_src和ucos_port

目录 ucos_conf 文件夹ucos_src 文件夹ucos_port 文件夹 在 uC/OS-II 中,ucos_conf、ucos_src 和 ucos_port 是三个不同的文件夹,它们的作用和功能有所不同: ucos_conf 文件夹 ucos_conf 文件夹:ucos_conf 文件夹包含了 uC/OS-II…

CSGO游戏里的饰品是如何被炒作起来的?

csgo倒狗们是如何操盘csgo饰品市场的? CSGO游戏里的饰品是如何被炒作起来的? 随着近几年csgo玩家数量急剧上升,倒狗在市场中的比例也在上升,之前的csgo饰品市场以散户居多,价格波动不大,现在倒狗大量涌入&a…

Docker学习——①

文章目录 1、什么是虚拟化、容器化?2、为什么要虚拟化、容器化?3、虚拟化实现方式3.1 应用程序执行环境分层3.2 虚拟化常见类别3.3 常见虚拟化实现3.3.1 主机虚拟化(虚拟机)实现3.3.2 容器虚拟化实现3.3.3 空间隔离实战--基础知识3.3.4 PID 隔离3.3.5 Mo…

【优选算法系列】【专题九链表】第一节.链表常用技巧和操作总结(2. 两数相加)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、链表常用技巧和操作总结二、两数相加 2.1 题目描述 2.2 题目解析 2.2.1 算法原理 2.2.2 代码编写总结 前言 一、链表常…

uniapp自定义权限菜单,动态tabbar

已封装为组件&#xff0c;亲测4个菜单项目可以切换&#xff0c; 以下为示例&#xff0c;根据Storage 中 userType 的 值&#xff0c;判断权限菜单 <template><view class"tab-bar pb10"><view class"tabli" v-for"(tab, index) in ta…

会声会影2024对比2023变化以及功能对比

全新会声会影2024版本现已登场&#xff0c;小伙伴们相信已经急不可待地想知道2024版到底有哪些新功能。对比2023版本&#xff0c;会声会影2024版本有没有功能的增强&#xff1f;事不宜迟&#xff0c;现在就让我们一起来看看会声会影2024对比2023的变化&#xff0c;包括功能对比…

什么是Babel?它的主要作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

编译正点原子LINUXB报错make: arm-linux-gnueabihf-gcc:命令未找到

编译正点原子LINUX报错make: arm-linux-gnueabihf-gcc&#xff1a;命令未找到 1.报错内容2.解决办法3./bin/sh: 1: lzop: not found4.编译成功 1.报错内容 make: arm-linux-gnueabihf-gcc&#xff1a;命令未找到CHK include/config/kernel.releaseCHK include/generat…

unity3d 开发笔记

unity 3d Unity是一个游戏引擎&#xff0c;包含渲染引擎&#xff0c;物理引擎&#xff0c;碰撞检测&#xff0c;音效&#xff0c;动画效果&#xff0c;场景管理等系统。它的开发效率高、脚本使用C#开发、简单易用、跨平台&#xff08;可以导出各个平台的程序&#xff09;&…

家庭用洗地机哪个最好?家用洗地机选购

家里日常打扫&#xff0c;维持地面的清洁&#xff0c;清洁干湿垃圾这时候必不可缺的就是洗地机了&#xff0c;由于近年来洗地机行业的热度高涨&#xff0c;涌现了很多洗地机品牌&#xff0c;这也让消费者在挑选的时候无从下手&#xff0c;今天笔者就给大家讲讲洗地机挑选需要主…

Linux 下C++工程编译

创建文件夹 #include<iostream> using namespace std;int main(){cout<<"THis is C program Process!"<<endl;}编译执行命令&#xff1a; g test.cpp -o test实际上&#xff0c;上述的命令包含了如下的四个过程&#xff1a; 1. 预处理 g -E …

东北大学python大作业

目前金属矿开采&#xff0c;爆破还是主要的破岩方式&#xff0c;为了保证巷道采场的安全&#xff0c;需要对爆破震动进行监测&#xff0c;获取的监测数据如附件&#xff0c;第1列数据为震动的序号&#xff0c;第2、3、4列为x,y,z三个方向的震动速度&#xff0c;往往由于各种因素…

【CSS】CSS基础知识扫盲

1、 什么是CSS&#xff1f; CSS即层叠样式表 (Cascading Style Sheets). CSS 能够对网页中元素位置的排版进行像素级精确控制, 实现美化页面的效果. 能够做到页面的样式和结构分离 2、 CSS引入方式 CSS代码编写的时候有多种引入方式&#xff1a; 内部样式、外部样式、内联样…

论文阅读:One Embedder, Any Task: Instruction-Finetuned Text Embeddings

1. 优势 现存的emmbedding应用在新的task或者domain上时表现会有明显下降&#xff0c;甚至在相同task的不同domian上的效果也不行。这篇文章的重点就是提升embedding在不同任务和领域上的效果&#xff0c;特点是不需要用特定领域的数据进行finetune而是使用instuction finetun…

linux centos7安装colmap

centos安装colmap 一、安装依赖 sudo yum install \gflags-devel \glog-devel \glew-devel \atlas \atlas-devel \lapack-devel \blas-devel \flann-devel \lz4-devel \sqlite-devel \metis-devel \qt5-qtbase-devel二、编译安装colmap git clone https://github.com/colmap/…

第18期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

Java 数据结构篇-模拟实现动态数组

&#x1f525;博客主页&#xff1a; 小扳_-CSDN博客 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 本篇目录 1.0 动态数组说明 2.0 模拟实现动态数组的核心方法 2.1 动态数组-插入与扩容 2.2 动态数组-获取元素 2.3 动态数组-修改元素 2.4 动态数组-删除元素 2.5 动态数组-遍历…

Flutter 04 按钮Button和事件处理、弹框Dialog、Toast

一、按钮组件 1、按钮类型&#xff1a; 2、按钮实现效果&#xff1a; import package:flutter/material.dart;void main() {runApp(const MyApp()); }class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);overrideWidget build(BuildContext co…

Langchain-Chatchat项目:4.2-P-Tuning v2使用的数据集

本文主要介绍P-tuning-v2论文中的5种任务&#xff0c;分别为Glue任务、NER任务、QA任务、SRL任务、SuperGlue任务&#xff0c;重点介绍了下每种任务使用的数据集。 一.Glue任务   GLUE&#xff08;General Language Understanding Evaluation&#xff09;是纽约大学、华盛顿…

Spring IOC详解

文章目录 目录 文章目录 前言 一 . SpringFramework介绍 1.1 Spring和SpringFramework概念 1.2 SpringFramework主要功能模块 二 . Spring IOC容器和核心概念 2.1 组件和组件管理 2.1.1 什么是组件? 2.1.2 组件管理 2.2 Spring IOC容器和容器实现 2.2.1 Sprign IO…