摘要:查询重写优化既可以基于关系代数的理论进行优化,也可以基于启发式规则进行优化。

本文分享自华为云社区《openGauss内核分析(四):查询重写》,作者:酷哥。

查询重写

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);

create table t2(c1 int, c2 int);

insert into t1 values(1, 10);

insert into t1 values(2, 20);

insert into t1 values(3, 30);

insert into t2 values(1, 100);

insert into t2 values(3, 300);

insert into t2 values(5, 500);

内连接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)

{

reduce_outer_joins_state* state = NULL;

state = reduce_outer_joins_pass1((Node*)root->parse->jointree);

/* planner.c shouldn't have called me if no outer joins */

if (state == NULL || !state->contains_outer)

ereport(ERROR,

(errmodule(MOD_OPT),

errcode(ERRCODE_OPTIMIZER_INCONSISTENT_STATE),

(errmsg("so where are the outer joins?"))));

reduce_outer_joins_pass2((Node*)root->parse->jointree, state, root, NULL, NIL, NIL);

}

利用上一期的分析方法,可以得到查询树内存结构(查询树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))

$1 = {type = T_JoinExpr, jointype = JOIN_INNER, isNatural = false, larg = 0x7fdfb345cd08, rarg = 0x7fdfb345e2e8, usingClause = 0x0, quals = 0x7fdfb2f0b8a8, alias = 0x0, rtindex = 3}

(gdb) p *(RangeTblEntry*)(parse->rtable->tail.data->ptr_value)

$2 = {type = T_RangeTblEntry, rtekind = RTE_JOIN, relname = 0x0, partAttrNum = 0x0, relid = 0, partitionOid = 0, isContainPartition = false, subpartitionOid = 0, isContainSubPartition = false,

refSynOid = 0, partid_list = 0x0, relkind = 0 '\000', isResultRel = false, tablesample = 0x0, timecapsule = 0x0, ispartrel = false, ignoreResetRelid = false, subquery = 0x0, security_barrier = false,

jointype = JOIN_INNER, …}

点击关注,第一时间了解华为云新鲜技术~

openGauss内核分析:查询重写的更多相关文章

  1. openGauss内核:SQL解析过程分析

    摘要:在传统数据库中SQL引擎一般指对用户输入的SQL语句进行解析.优化的软件模块.SQL的解析过程主要分为:词法.语法和语义分析. 本文分享自华为云社区< openGauss内核分析(三):S ...

  2. SQL Server索引视图以(物化视图)及索引视图与查询重写

    本位出处:http://www.cnblogs.com/wy123/p/6041122.html 经常听Oracle的同学说起来物化视图,物化视图的作用之一就是可以实现查询重写,听起来有一种高大上的感 ...

  3. linux内核分析作业5:分析system_call中断处理过程

    1.增加 Menu 内核命令行 调试系统调用. 步骤:删除menu git clone        (tab) make rootfs 这就是我们将 fork 函数写入 Menu 系统内核后的效果, ...

  4. 《Linux内核分析》第五周 扒开系统调用的三层皮(下)

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK FIVE( ...

  5. Linux内核分析第五周学习总结:扒开系统调用的三层皮(下)

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.给MenuO ...

  6. LINUX内核分析期末总结

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.课程总结 1 ...

  7. 《Linux内核分析》实践4

    <Linux内核分析> 实践四--ELF文件格式分析 20135211李行之 一.概述 1.ELF全称Executable and Linkable Format,可执行连接格式,ELF格 ...

  8. LINUX内核分析第五周学习总结——扒开系统调用的“三层皮”(下)

    LINUX内核分析第五周学习总结--扒开系统调用的"三层皮"(下) 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>M ...

  9. Linux内核分析——第五周学习笔记

    第五周 扒开系统调用的“三层皮”(下) 一.知识点总结 (一)给MenuOS增加time和time-asm命令 在实验楼中,首先 强制删除menu (rm menu -rf) 重新克隆一个新版本的me ...

  10. linux内核分析第五周学习笔记

    linux内核分析第五周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

随机推荐

  1. 如何在云服务上快速拥有洛甲WAF(Web防火墙)

    如何在云服务上快速拥有洛甲WAF(Web防火墙) 洛甲WAF是基于openresty的web防火墙,通过配合后台保护您的数据安全,详情参考节点服务器 luojiawaf_lua(nginx+lua) ...

  2. IDEA工具第二篇:自定义Java方法注释模板

    网上搜索类似的文章有很多,但是一味的复制粘贴总会出现各种奇葩问题,最后然并卵!今天特意自己研究琢磨一下,将最终结果分享给大家,100%亲测可用. 一.说明 想必大家都用过Eclipse的方法注释生成, ...

  3. ACL 与NAT

    ACL 概述 acl是由一系列permit或deny语句组成.有序规则的列表. ACL是一个匹配工具,能够对报文进行匹配和区分. 应用 匹配流量 在traffic-filter中备调用 在NAT中被调 ...

  4. Jenkins软件平台安装部署

    1.Jenkins软件平台概念剖解: 基于主流的Hudson/Jenkins平台工具实现全自动网站部署.网站测试.网站回滚会大大的减轻网站部署的成本,Jenkins的前身为Hudson,Hudson主 ...

  5. 特殊符号传到后端发生变异 &amp; &quot;&lt;&gt;

    业务遇到bug,前端传回数据 & ,到后台接收到的数据就是 & 后台接收到的数据就携带了amp;的后缀 网上查找原因,大部分说法是前端传回的数据导致,但是实际并不是,这里是框架的正则过 ...

  6. Ansible操作MySQL常用的几个模块

    1. mysql_user 模块 mysql_user模块用来添加,删除用户以及设置用户权限 创建MySQL数据库的用户与口令(非root@localhost用户),直接通过playbooks中的案例 ...

  7. Java系列:Java8 新特性:强大的 Stream API(创建 Stream、中间操作、终止操作)

    Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API. Stream API ( java.util.stream) 把真正的函数式编程风格引入到Jav ...

  8. NativeBuffering,进一步提升字符串的序列化性能

    在<NativeBuffering,一种高性能.零内存分配的序列化解决方案[性能测试篇]>我比较了NativeBuffering和System.Text.Json两种序列化方式的性能,通过 ...

  9. Log4j入门使用

    前言 本篇文章主要在于,初步了解log4j,以及对它的简单使用 欢迎点赞 收藏 留言评论 私信必回哟 博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言 @ 目录 一,log4j简介 二,配 ...

  10. 用友NCC产品API使用指南

    轻易云用友NCC产品API集成专题 open api简介 Open API即开放API,也称开放平台. 所谓的开放API(OpenAPI)是服务型网站常见的一种应用,网站的服务商将自己的网站服务封装成 ...