---
title: openGauss内核分析（四）：查询重写-官方技术文章-鲲鹏社区
description: 查询重写就是把用户输入的SQL语句转换为更高效的等价SQL，查询重写遵循两个基本原则。
keywords: Gauss,内核分析,查询重写,官方技术文章,鲲鹏社区,Outer,Inner,外连接消除
url: https://www.hikunpeng.com/developer/techArticles/20221101-2?envFlag=1
section: (其他)
---

# openGauss内核分析（四）：查询重写-官方技术文章-鲲鹏社区

URL: https://www.hikunpeng.com/developer/techArticles/20221101-2?envFlag=1
描述: 查询重写就是把用户输入的SQL语句转换为更高效的等价SQL，查询重写遵循两个基本原则。
关键词: Gauss,内核分析,查询重写,官方技术文章,鲲鹏社区,Outer,Inner,外连接消除

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

openGauss内核分析（四）：查询重写

openGauss内核分析（四）：查询重写

openGauss

发表于 2022/11/08

0

## 查询重写

SQL语言是丰富多样的，非常的灵活，不同的开发人员依据经验的不同，手写的SQL语句也是各式各样，另外还可以通过工具自动生成。SQL语言是一种描述性语言，数据库的使用者只是描述了想要的结果，而不关心数据的具体获取方式，输入数据库的SQL语言很难做到是以最优形式表示的，往往隐含了一些冗余信息，这些信息可以被挖掘用来生成更加高效的SQL语句。查询重写就是把用户输入的SQL语句转换为更高效的等价SQL，查询重写遵循两个基本原则。

- 等价性：原语句和重写后的语句，输出结果相同。
- 高效性：重写后的语句，比原语句在执行时间和资源使用上更高效。

查询重写优化既可以基于关系代数的理论进行优化，例如谓词下推、子查询优化等，也可以基于启发式规则进行优化，例如Outer Join消除、表连接消除等。查询重写是基于规则的逻辑优化。

在代码层面，查询重写的架构如下：

下面以外连接消除Outer2Inner—外连接转内连接为例分析查询重写过程：在left outer join或者right outer join中，如果查询条件中存在逻辑上能够包含IS NOT NULL，例如c1 > 0，可以将查询转换成INNER JOIN，从而减少关联处理产生的中间结果集。

## 外连接消除Outer2Inner

下面首先以一个例子来说明各种多表连接方式的区别：

- 
- 
- 
- 
- 
- 
- 
- 

```
create table t1(c1 int, c2 int);
```

内连接inner join：返回两个表都满足的组合，相当于取两个表的交集。

- 

```
SELECT * FROM t1 inner JOIN t2 ON t1.c1 = t2.c1;
```

左连接 left outer join：返回左表中的所有行，如果左表中行在右表中没有匹配行，则结果中右表中的列返回空值。

- 

```
SELECT * FROM t1 Left OUTER JOIN t2 ON t1.c1 = t2.c1;
```

右连接 right outer join：返回右表中的所有行，如果右表中行在左表中没有匹配行，则结果中左表中的列返回空值。

- 

```
SELECT * FROM t1 right OUTER JOIN t2 ON t1.c1 = t2.c1;
```

全连接 full join：返回左表和右表中的所有行。当某行在另一表中没有匹配行，则另一表中的列返回空值，相当于取两个表并集。

- 

```
SELECT * FROM t1 full JOIN t2 ON t1.c1 = t2.c1;
```

在以上实验的基础上增加t2表的where条件。

left join和inner join的结果是一样的，这是因为查询条件中包含WHERE t2.c2 >100这个条件，t2表所有不匹配元组均被过滤掉（包括空值），因此可以进行查询转换left-outer join -> inner join，能够有效减小t1和t2关联产生的结果集，达到性能提升的目的。

在openGauss数据库系统中，subquery_planner会遍历查询树中的rtable，看看是否有RTE_JOIN类型的节点存在，设置hasOuterJoins标志量，从而进入到reduce_outer_joins接口，满足外连接消除条件时再执行外连接的消除。reduce_outer_Joins函数内部做两个动作：

（1）reduce_outer_joins_pass1预检查，就是检查jointree中是否含有外链接，以及一些引用表的信息，为动作2做好信息采集准备，重点参考数据结构reduce_outer_joins_state；

（2）reduce_outer_joins_pass2真正完成消除外链接。

- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 

```
void reduce_outer_joins(PlannerInfo* root)
```

利用上一期的分析方法，可以得到查询树内存结构（查询树Query结构体中targetList存储目标属性语义分析结果，rtable存储FROM子句生成的范围表，jointree的quals字段存储WHERE子句语义分析的表达式树）

对比reduce_outer_joins运行前后查询树，jointree和rtable中的jointype都由join_left转换为join_inner，即外连接已转为内连接。

- 
- 
- 
- 
- 
- 

```
(gdb) p *((JoinExpr*)(parse->jointree->fromlist->head.data->ptr_value))
```

本页内容
