---
title: 带你走进openGauss数据库核心技术（一）-官方技术文章-鲲鹏社区
description: 本文将对SQL引擎的各个模块进行全面的说明。
keywords: Gauss,带你走进,数据库核心技,官方技术文章,鲲鹏社区,SQL,引擎概览,解析
url: https://www.hikunpeng.com/developer/techArticles/20230911-4?envFlag=1
section: (其他)
---

# 带你走进openGauss数据库核心技术（一）-官方技术文章-鲲鹏社区

URL: https://www.hikunpeng.com/developer/techArticles/20230911-4?envFlag=1
描述: 本文将对SQL引擎的各个模块进行全面的说明。
关键词: Gauss,带你走进,数据库核心技,官方技术文章,鲲鹏社区,SQL,引擎概览,解析

官方技术文章 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles)

带你走进openGauss数据库核心技术（一）

带你走进openGauss数据库核心技术（一）

实战经验

发表于 2020/07/23

0

前言：

SQL引擎是数据库重要的子系统之一，它对上负责承接应用程序过来的SQL语句，对下负责指挥执行器运行执行计划。其中优化器作为SQL引擎中最重要、最复杂的模块，被称为数据库的“大脑”，优化器产生的执行计划的优劣直接决定数据库的性能。本文将对SQL引擎的各个模块进行全面的说明。

## SQL引擎概览

SQL引擎是数据库系统重要组成部分，它的主要职责是负责将应用程序输入的SQL在当前负载场景下生成高效的执行计划，在SQL的高效执行上扮演重要角色。SQL在SQL引擎里的执行过程如图所示。

SQL执行流程：

从上图中可以看出，应用程序的SQL需要经过SQL解析生成逻辑执行计划、经过查询优化生成物理执行计划，然后将物理执行计划转交给查询执行引擎做物理算子的执行操作。

## SQL解析

SQL语句在数据库管理系统中的编译过程符合编译器实现的常规过程，需要进行词法分析、语法分析和语义分析。

在SQL语言标准中，了SQL语言的关键字以及语法规则信息，SQL解析器在做词法分析的过程中会将一个SQL语句根据关键字信息以及间隔信息划分为独立的原子单位，每个单位以一个词的方式展现，例如如下SQL语句：

（1） 词法分析：从查询语句中识别出系统支持的关键字、标识符、操作符、终结符等，每个词自己固有的词性。

（2） 语法分析：根据SQL语言的标准定义语法规则，使用词法分析中产生的词去匹配语法规则，如果一个SQL语句能够匹配一个语法规则，则生成对应的抽象语法树（Abstract Syntax Tree，AST）。

（3）语义分析：对语法树（AST）进行有效性检查，检查语法树中对应的表、列、函数、表达式是否有对应的元数据，将抽象语法树转换为逻辑执行计划（关系代数表达式）。

```
SELECT w_name FROM warehouse WHERE w_no = 1;
```

可以划分的关键字、标识符、操作符、常量等原子单位，如下表所示。

| 词性 | 内容 |
| --- | ---|
| 关键词 | SELECT、FROM、WHERE |
| 标识符 | w_name、warehouse、w_no |
| 操作符 | = |
| 常量 | 1 |

语法分析会根据词法分析获得的词来匹配语法规则，最终生成一个抽象语法树（AST），每个词作为语法树的叶子结点出现，如下图所示。

抽象语法树：

抽象语法树表达的语义还仅仅限制在能够保证应用的SQL语句符合SQL标准的规范，但是对于SQL语句的内在含义还需要做有效性的检查。

（1） 检查关系的使用：FROM子句中出现的关系必须是该查询对应模式中的关系或视图。

（2） 检查与解析属性的使用：在SELECT句中或者WHERE子句中出现的各个属性必须是FROM子句中某个关系或视图的属性。

（3） 检查数据类型：所有属性的数据类型必须是匹配的。

在有效性检查的同时，语义分析的过程还是有效性语义绑定（Bind）的过程，通过语义分析的检查，抽象语法树就转换成一个逻辑执行计划，逻辑执行计划可以通过关系代数表达式的形式来表现，如下图所示。

关系代数表达式：

## 查询优化

依据优化方法的不同，优化器的优化技术可以分为：

（1）基于规则的查询优化（Rule Based Optimization，RBO）：根据预定义的启发式规则对SQL语句进行优化。

（2）基于代价的查询优化（Cost Based Optimization，CBO）：对SQL语句对应的待选执行路径进行代价估算，从待选路径中选择代价最低的执行路径作为最终的执行计划。

（3）基于机器学习的查询优化（AI Based Optimization，ABO）：收集执行计划的特征信息，借助机器学习模型获得经验信息，进而对执行计划进行调优，获得最优的执行计划。

近年来AI技术，特别是在深度学习领域，发展迅速，基于机器学习的优化器在建模效率、估算准确率和自适应性等方面都有很大优势，有望打破RBO和CBO基于静态模型的限制，通过对历史经验的不断学习，将目标场景的模式进行抽象化，形成动态的模型，自适应地针对用户的实际场景进行优化。openGauss采用基于CBO的优化技术，另外在ABO方面也在进行积极探索。

### 1. 查询重写

查询重写就是把用户输入的SQL语句转换为更高效的等价SQL，查询重写遵循两个基本原则：

等价性：原语句和重写后的语句，输出结果相同。

高效性：重写后的语句，比原语句在执行时间和资源使用上更高效。

### 2. 常见的查询重写技术

openGauss几个关键的查询重写技术：常量表达式化简、子查询优化、选择下推和等价推理等。

（1）常量表达式化简

常量表达式即用户输入SQL语句中包含运算结果为常量的表达式，分为算数表达式、逻辑运算表达式、函数表达式，查询重写可以对常量表达式预先计算以提升效率。

示例1：该语句为典型的算数表达式查询重写，经过重写之后，避免了在执行时每条数据都需要进行1+1运算。

```
SELECT * FROM t1 WHERE c1 = 1+1;
SELECT * FROM t1 WHERE c1 = 2;
```

示例2：该语句为典型的逻辑运算表达式，经过重写之后，条件永远为false，可以直接返回0行结果，避免了整个语句的实际执行。

```
SELECT * FROM t1 WHERE  1=0  AND a=1;
SELECT * FROM t1 WHERE  false;
```

示例3：该语句包含函数表达式，由于函数的入参为常量，经过重写之后，直接把函数运算结果在优化阶段计算出来，避免了在执行过程中逐条数据的函数调用开销。

```
SELECT * FROM t1 WHERE c1 =  ADD(1,1);
SELECT * FROM t1 WHERE c1 =  2;
```

（2）子查询优化

由于子查询表示的结构更清晰，符合人的阅读理解习惯，用户输入的SQL语句往往包含了大量的子查询。子查询有几种分类方法，根据子查询是否可以独立求解，分为相关子查询和非相关子查询。

相关子查询：相关子查询是指子查询中有依赖父查询的条件，例如：

```
SELECT * FROM t1 WHERE EXISTS (SELECT t2.c1 FROM t2 WHERE t1.c1=t2.c1);
```

语句中子查询依赖父查询传入t1.c1的值。

非相关子查询：非相关子查询是指子查询不依赖父查询，可以独立求解，例如：

```
SELECT * FROM t1 WHERE c1 = 1+1;
SELECT * FROM t1 WHERE c1 = 2;

SELECT * FROM t1 WHERE EXISTS (SELECT t2.c1 FROM t2)
```

语句中子查询没有依赖父查询的条件。

其中，相关子查询需要父查询执行出一条结果，然后驱动子查询运算，这种嵌套循环的方式执行效率较低。如果能把子查询提升为父查询同级别，那么可以子查询中的表就能和父查询中的表直接做Join操作，由于Join操作可以有多种实现方法，优化器就可以从多种实现方法中选择最优的一种，就有可能提高查询的执行效率，另外优化器还能够应用Join Reorder优化规则对不同的表的连接顺序进行交换，进而有可能产生更好的执行计划。

示例：该语句为典型的子查询提升重写，重写之后利用Hash Join可以提升查询性能。

```
SELECT * FROM t1 WHERE t1.c1 IN (SELECT t2.c1 FROM t2);
SELECT * FROM t1 Semi Join t2 ON t1.c1 = t2.c1;
```

（3）选择的下推和等价推理

选择的下推能够极大的降低上层算子的计算量，从而达到优化的效果，如果选择条件有存在等值操作，那么还可以借助等值操作的特性来实现等价推理，从而获得新的选择条件。

例如，假设有两个表t1、t2分别包含[1,2,3,..100]共100行数据，那么查询语句

```
SELECT t1.c1, t2.c1 FROM t1 JOIN t2 ON t1.c1=t2.c1 WHERE t1.c1=1；
```

查询重写前后对比图：

（4）外连接消除

外连接和内连接的主要区别是对于不能产生连接结果的元组需要补NULL值，如果SQL语句中有过滤条件符合空值拒绝的条件（即会将补充的NULL值再过滤掉），则可以直接消除外连接。

示例：外连接转成内连接之后，便于优化器应用更多的优化规则，提高执行效率。

```
SELECT * FROM t1  FULL JOIN t2 ON t1.c1 = t2.c1 WHERE t1.c2 > 5 AND t2.c3 < 10;
SELECT * FROM t1  INNER JOIN  t2 ON t1.c1 = t2.c2 WHERE t1.c2 > 5 AND t2.c3 < 10;
```

（5）DISTINCT消除

DISTINCT列上如果有主键约束，则此列不可能为空，且无重复值，因此不需要DISTINCT操作，减少计算量。

示例：c1列上有的主键属性决定了无需做DISTINCT操作。语句如下：

```
CREATE TABLE t1(c1 INT PRIMARY KEY, c2 INT);
SELECT  DISTINCT(c1) FROM t1;
SELECT c1 FROM t1;
```

（6）IN谓词展开

示例：将IN操作符改写成等值的过滤条件，便于借助索引减少计算量。语句如下：

```
SELECT * FROM t1 WHERE  c1 IN (10,20,30);
SELECT * FROM t1 WHERE  c1=10 or c1=20 OR c1=30;
```

（7）视图展开

视图从逻辑上可以简化书写SQL的难度，提高查询的易用性，而视图本身是虚拟的，因此在查询重写的过程中，需要对视图展开。

示例：可以将视图查询重写成子查询的形式，然后再对子查询做简化。语句如下：

```
CREATE VIEW v1 AS (SELECT * FROM t1,t2 WHERE t1.c1=t2.c2);
SELECT * FROM v1;
SELECT * FROM (SELECT * FROM t1,t2 WHERE t1.c1=t2.c2) as v1;
SELECT * FROM t1,t2 WHERE t1.c1=t2.c2;
```

openGauss开源社区官方网站：

https://opengauss.org/ [了解详情](https://opengauss.org)

openGauss组织仓库：

https://gitcode.com/opengauss [了解详情](https://gitcode.com/opengauss)

openGauss镜像仓库：

https://github.com/opengauss-mirror [了解详情](https://github.com/opengauss-mirror)

本页内容
