上一节我们介绍了PostgreSQL的子查询优化,子查询优化把一部分可以优化的子查询上拉到主查询成为join。

preprocess_expression

将表达式(目标列,where,join,having)简化表达式

static Node *
preprocess_expression(PlannerInfo *root, Node *expr, int kind)
{
/*
* If the query has any join RTEs, replace join alias variables with
* base-relation variables. We must do this before sublink processing,
* else sublinks expanded out from join aliases would not get processed.
* We can skip it in non-lateral RTE functions, VALUES lists, and
* TABLESAMPLE clauses, however, since they can't contain any Vars of the
* current query level.
*/
if (root->hasJoinRTEs &&
!(kind == EXPRKIND_RTFUNC ||
kind == EXPRKIND_VALUES ||
kind == EXPRKIND_TABLESAMPLE))
expr = flatten_join_alias_vars(root, expr); //简化常量表达式,特别处理and和or
expr = eval_const_expressions(root, expr); //标准化条件表达式(where和having)
if (kind == EXPRKIND_QUAL)
{
expr = (Node *) canonicalize_qual((Expr *) expr);
} /* 求解子链接的表达式,对于不能上拉的子链接会递归调用subquery_planner */
if (root->parse->hasSubLinks)
expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL)); /* 给相关子查询替换变量SubPlan */
if (root->query_level > 1)
expr = SS_replace_correlation_vars(root, expr); /*把where和having中的and表达式转换为隐含形式*/
if (kind == EXPRKIND_QUAL)
expr = (Node *) make_ands_implicit((Expr *) expr); return expr;
}

eval_const_expressions

canonicalize_qual

使用OR分配律简化逻辑表达式,得到顶层全是AND的表达式。例如:

((A AND B) OR (A AND C)) -> (A AND (B OR C))

reduce_outer_joins

void
reduce_outer_joins(PlannerInfo *root)
{
reduce_outer_joins_state *state; /*
* To avoid doing strictness checks on more quals than necessary, we want
* to stop descending the jointree as soon as there are no outer joins
* below our current point. This consideration forces a two-pass process.
* The first pass gathers information about which base rels appear below
* each side of each join clause, and about whether there are outer
* join(s) below each side of each join clause. The second pass examines
* qual clauses and changes join types as it descends the tree.
*/
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)
elog(ERROR, "so where are the outer joins?"); reduce_outer_joins_pass2((Node *) root->parse->jointree,
state, root, NULL, NIL, NIL);
} static void
reduce_outer_joins_pass2(Node *jtnode,
reduce_outer_joins_state *state,
PlannerInfo *root,
Relids nonnullable_rels,
List *nonnullable_vars,
List *forced_null_vars)
{
else if (IsA(jtnode, JoinExpr))
{
switch (jointype)
{
case JOIN_INNER:
break;
case JOIN_LEFT://优化为内连接
if (bms_overlap(nonnullable_rels, right_state->relids))
jointype = JOIN_INNER;
break;
case JOIN_RIGHT://优化为内连接
if (bms_overlap(nonnullable_rels, left_state->relids))
jointype = JOIN_INNER;
break;
case JOIN_FULL:
if (bms_overlap(nonnullable_rels, left_state->relids))
{
if (bms_overlap(nonnullable_rels, right_state->relids))
jointype = JOIN_INNER;//优化为内连接
else
jointype = JOIN_LEFT;//优化为左外连接
}
else
{
if (bms_overlap(nonnullable_rels, right_state->relids))
jointype = JOIN_RIGHT;//优化为右外连接
}
break;
case JOIN_SEMI:
case JOIN_ANTI:
break;
default:
elog(ERROR, "unrecognized join type: %d",
(int) jointype);
break;
} /*剩余的右外连接优化为左外连接*/
if (jointype == JOIN_RIGHT)
{
} /*左外连接转换为反半连接*/
if (jointype == JOIN_LEFT)
{
} /* 递归优化之树 */
if (left_state->contains_outer || right_state->contains_outer)
{
if (left_state->contains_outer)
{
reduce_outer_joins_pass2(j->larg, left_state, root,
pass_nonnullable_rels,
pass_nonnullable_vars,
pass_forced_null_vars);
} if (right_state->contains_outer)
{
reduce_outer_joins_pass2(j->rarg, right_state, root,
pass_nonnullable_rels,
pass_nonnullable_vars,
pass_forced_null_vars);
}
bms_free(local_nonnullable_rels);
}
}
else
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(jtnode));
}

消除外连接,不是所有的外连接都能转换为内连接,只有基于"空值拒绝"的才可以。其实SQL还是外连接,只是这样可以通过调整多表连接顺序优化。

例如:left join,join后右边的列被非空条件排除

select * from x left join y on (x.x = y.y) where y.y is not null;

优化后只有FULL JOIN

PostgreSQL查询优化逻辑优化之其他的更多相关文章

  1. PostgreSQL查询优化简介

    简介 PostgreSQL查询优化器执行过程 语法分析:生成查询树 语义检查:对SQL表达的语义进行检查 查询优化 视图重写 逻辑优化:子查询优化,条件化简,等价谓词重写,连接消除,得到逻辑计划 物理 ...

  2. PostgreSQL查询优化器之grouping_planner

    grouping_planner主要做了3个工作: 对集合进行处理 对非SPJ函数进行优化 对SQL查询语句进行物理优化 grouping_planner实现代码如下: static void gro ...

  3. Scrum立会报告+燃尽图(十二月六日总第三十七次):程序功能逻辑优化

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2284 项目地址:https://git.coding.net/zhang ...

  4. SQL 查询优化 索引优化

    sql语句优化 性能不理想的系统中除了一部分是因为应用程序的负载确实超过了服务器的实际处理能力外,更多的是因为系统存在大量的SQL语句需要优化. 为了获得稳定的执行性能,SQL语句越简单越好.对复杂的 ...

  5. PostgreSQL之性能优化(转)

    转载自:https://blog.csdn.net/huangwenyi1010/article/details/72853785 解决问题 前言 PostgreSQL的配置参数作为性能调优的一部分, ...

  6. 数据库查询优化-SQL优化

    1.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默 ...

  7. PostgreSQL查询优化之子查询优化

    子查询优化 上拉子连接 上拉子连接主要是把ANY和EXIST子句转换为半连接 void pull_up_sublinks(PlannerInfo *root) { Node *jtnode; //子连 ...

  8. SQL 逻辑优化 case when 转为 union all

    通常数据库的优化从硬件层面去考虑可分为4个方面: CPU:即降低计算复杂度,如减少sql各类聚合函数,窗口函数,case when等. IO :(较少查询结果集过程中对数据的访问量.数据优化很大程度从 ...

  9. PostgreSQL的参数优化

    硬件和软件信息 CPU: Intel(R) Xeon(R) CPU E5-2683 v3 @ 2.00GHz 2 sockets / 28 cores / 56 threads内存: 256GB of ...

随机推荐

  1. elementui上传文件

    <el-form-item label="上传附件"> <transition name="fade"> <el-upload r ...

  2. 网站开发,推荐使用SuperSlide 插件-Tab标签切换,图片滚动,无缝滚动,焦点图

    SuperSlide 致力于解决网站大部分特效展示问题,使网站代码规范整洁,方便维护更新.网站上常用的“焦点图/幻灯片”“Tab标签切换”“图片滚动”“无缝滚动”等只需要一个SuperSlide即可解 ...

  3. oracle数据库卸数及ddl导出

    一.数据库卸数脚本 还是比较明了的,一看就明白. unloaddevice.sh sqlplus atmpbat/atmpbat@inter @"./unloaddevice.sql&quo ...

  4. Golang中的三个点

    之前提到了把一个切片追加到另外一个切片时使用到了... 今天我们好好研究一下这三个点,博客写着写着又成了,回字有四种写法 ...第一种用法,可变长的参数 package main import &qu ...

  5. merge and saveorupdate

    首先 saveOrUpdate返回void 也就是什么都不返回 而merge会返回一个对象 merge 在执行session.merge(a)代码后,a对象仍然不是持久化状态,a对象仍然不会被关联到S ...

  6. selenium实现淘宝的商品爬取

    一.问题 本次利用selenium自动化测试,完成对淘宝的爬取,这样可以避免一些反爬的措施,也是一种爬虫常用的手段.本次实战的难点: 1.如何利用selenium绕过淘宝的登录界面 2.获取淘宝的页面 ...

  7. 归并排序(递归排序and外排排序)

    分析: /** * 归并排序 (先将数组利用归并排序排成 有序的左边数组和右边数组,再比较左边数组和右边数组的数值大小进行排序) * */ public class MergeSort { publi ...

  8. windows 函数

    数组清零 ::ZeroMemory(首地址,大小);

  9. Spring mvc解决url传递中文参数乱码问题

    在tomcat服务器中,修改server.xml参数,如<Connector URIEncoding="UTF-8" connectionTimeout="2000 ...

  10. 安装zookeeper(单机,伪集群)

    1.登陆zookeeper官网下载 https://zookeeper.apache.org/ zookeeper-3.4.8.tar.gz 解压:tar -zxvf zookeeper-3.4.8. ...