上一节我们介绍了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. [费用流][BZOJ1070]修车

    修车 题目描述 同一时刻有位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均 ...

  2. redis持久化详述

    本来打算根据自己搜索的一些文章写些总结,后来发现了一篇好文,这里转载下,在自己博客里面记录下. 原文链接:https://www.cnblogs.com/kismetv/p/9137897.html ...

  3. js的事件委托机制

    如今的JavaScript技术界里最火热的一项技术应该是‘事件委托(event delegation)’了.使用事件委托技术能让你避免对特定的每个节点添加事件监听器:相反,事件监听器是被添加到它们的父 ...

  4. To handling editor letter

    一般崔稿信写法: Dear Editor: Sorry for disturbing you. We’re not sure if it is the right time to contact yo ...

  5. android activity之间用广播传输数据

    发送者: Intent intent = new Intent("com.BroadcastAction"); intent.putExtra("result" ...

  6. lwip-动态内存管理

    动态内存管理涉及两类重要函数,内存分配函数,内存释放函数,如C语言中的malloc和free. 内存分配的本质是:在事先准好一大块内存堆(可以理解为一个很大的数组)中分配合适的空间,然后将该空间起始地 ...

  7. Pattern Design - Strategy Pattern

    If you can disassemble code  and  you want to apply one method of an object in another object that t ...

  8. Dynamic Programming | Set 4 (Longest Common Subsequence)

    首先来看什么是最长公共子序列:给定两个序列,找到两个序列中均存在的最长公共子序列的长度.子序列需要以相关的顺序呈现,但不必连续.例如,"abc", "abg", ...

  9. 背水一战 Windows 10 (75) - 控件(控件基类): FrameworkElement - 基础知识, 相关事件, HorizontalAlignment, VerticalAlignment

    [源码下载] 背水一战 Windows 10 (75) - 控件(控件基类): FrameworkElement - 基础知识, 相关事件, HorizontalAlignment, Vertical ...

  10. 基于ε-NFA的正则表达式引擎

    正则表达式几乎每个程序员都会用到,对于这么常见的一个语言,有没有想过怎么去实现一个呢?乍一想,也许觉得困难,实际上实现一个正则表达式的引擎并没有想像中的复杂,<编译原理>一书中有一章专门讲 ...