【PostgreSQL内核学习(五)—— 查询规划(预处理)】

news2024/12/25 10:32:08

查询规划——预处理

  • 预处理
    • 提升子链接/子查询
    • 预处理表达式
    • 预处理HAVING子句

声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。
本文主要参考了《PostgresSQL数据库内核分析》一书

预处理

  前面说过,在实际进行计划生成之前将对查询树做一些预处理,预处理的主要工作是提升子链接和子查询以及预处理表达式和HAVING子句等。预处理部分主要是对查询树Query中的范围表rtable和连接树jointree等进行处理。
  查询规划的预处理阶段是查询优化的第一步,其目的是对用户提交的查询进行初步处理和解析,准备生成查询树。预处理阶段包括以下主要步骤:

  1. 词法和语法分析:将用户输入的SQL查询语句转换成抽象语法树(AST)的形式,将查询语句拆分成独立的语法单元,检查语法是否合法。
  2. 语义分析:对查询进行语义检查,验证表、列等数据库对象的存在性和合法性,检查查询语句是否符合数据库规则。
  3. 名称解析:解析查询语句中的标识符(如表名、列名、别名等),将它们与数据库中的实际对象进行绑定,以便后续阶段能够正确地处理这些对象。
  4. 权限检查:检查用户是否有执行查询所需的权限,如果没有权限,则阻止查询执行。
  5. 优化器挑选:在预处理阶段,优化器可能根据查询特性进行一些简单的优化,如选择最佳的连接顺序、使用合适的索引等。

  预处理阶段完成后,生成了一个包含查询信息的解析树(Parse Tree)。这个解析树会被进一步处理,进行查询重写、路径生成和生成计划等优化过程,最终生成可执行的查询计划并执行查询。

提升子链接/子查询

  子查询(Subquery)和子链接(Sublink)是两个不同的概念,它们在SQL查询中有不同的用途和作用。

子查询(Subquery)
  子查询是指一个完整的查询语句嵌套在另一个查询语句中的查询。它通常作为主查询的条件或数据源来限制或过滤主查询的结果集。子查询可以出现在SELECT、FROM、WHERE、HAVING等子句中,并返回一个单一值、一组值或一个结果集供主查询使用。

  例如,在以下SQL语句中,子查询用作WHERE子句中的条件:

SELECT * FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'HR');

子链接(Sublink):
  子链接是优化器在查询规划阶段对子查询的一种处理方式。它将子查询转换成一个虚拟的关系表(虚拟表),并将其视为一个普通的表参与查询规划的过程。子链接有时也称为“提升子查询”或“优化子查询”。
  子链接的作用是将子查询的结果缓存为一个虚拟表,以避免在每次查询时都重复执行子查询。这样做可以提高查询性能,特别是在子查询较为复杂或返回结果集较大时。

  在查询规划的预处理阶段中,“提升子链接”,也称为"提升子查询",是一种优化技术用于将子查询转换为更高效的连接操作,以提高整体查询性能
  通常,子查询是嵌套在主查询中的查询语句,它会在主查询的执行过程中被执行多次。这可能导致性能问题,特别是当子查询返回大量数据时。
  "提升子链接"的目的是将子查询转换为连接操作或使用关联子查询等方式,以减少子查询的执行次数,从而减少不必要的开销。这样可以有效地优化查询计划,提高查询性能。
  这里分别对 查询块嵌套查询嵌套子查询 这几个名词进行解释。

  1. 查询块(Query Block):
      查询块是指一个独立的查询语句或子查询,在SQL语句中通常由一个SELECT、INSERT、UPDATE、DELETE等关键字引导,并包含其后的所有相关子句。查询块可以是整个SQL语句,也可以是一个复杂查询中的一部分。查询块的作用是定义一个查询的逻辑结构和语义,它可以由优化器进行优化和执行

例如,在以下SQL语句中,有两个查询块:主查询块和子查询块。

SELECT * FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'HR');
  1. 嵌套查询(Nested Query):
      嵌套查询是指一个查询语句中包含了另一个完整的查询语句,也称为子查询。嵌套查询的内部查询通常被称为子查询,外部查询称为主查询。嵌套查询允许在查询中使用查询的结果作为另一个查询的条件或数据源,从而实现更复杂的查询需求。

例如,在以下SQL语句中,就有一个嵌套查询:

SELECT * FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'HR');
  1. 嵌套子查询(Nested Subquery):
      嵌套子查询是指在一个查询语句的条件中使用了一个完整的子查询。嵌套子查询与嵌套查询的概念相似,但重点在于嵌套子查询作为主查询的条件之一,用于限制主查询的结果集。

例如,在以下SQL语句中,嵌套子查询用于限制主查询的结果集:

SELECT * FROM employees WHERE department_id IN (SELECT department_id FROM departments WHERE location = 'New York');

  按相关性,嵌套查询可分为相关子查询非相关子查询。相关子查询是指该子查询的执行依赖于外层父查询的某些属性值。它需要接受父查询的参数,因此会设置相关标记,当参数改变的时候,需要重置参数后重新执行一遍子查询得到新的结果。非相关子查询中子查询完全可以独立。

  1. 相关子查询(Correlated Subquery):
      相关子查询是指子查询中的条件依赖于外部查询的结果,在子查询中使用了外部查询的列值。换句话说,子查询的执行依赖于外部查询的每一行。相关子查询在执行时会为外部查询的每一行执行一次,并根据外部查询的值来计算子查询的结果。
      例如,在以下SQL语句中,子查询中的条件依赖于外部查询的employee_id
SELECT * FROM employees e
WHERE salary > (SELECT AVG(salary) FROM employees WHERE department_id = e.department_id);

  1. 非相关子查询(Non-Correlated Subquery):
      非相关子查询是指子查询中的条件与外部查询无关,子查询的执行不依赖于外部查询的结果。非相关子查询在执行时只执行一次,不受外部查询的影响,可以独立地计算子查询的结果。
      例如,在以下SQL语句中,子查询中的条件与外部查询无关,只需要执行一次来计算最大的salary:
SELECT * FROM employees
WHERE salary > (SELECT MAX(salary) FROM employees);

总结:相关子查询是子查询中的条件依赖于外部查询的结果,会为外部查询的每一行执行一次。非相关子查询是子查询中的条件与外部查询无关,只执行一次。

预处理表达式

  表达式的预处理工作由函数preprocess_expression完成,处理的对象有:目标属性、HAVING子句、OFFSET 和 LIMIT子句、连接树preprocess_expression 采用递归扫描的方式对PlannerImfo结构中的表达式进行处理。
  preprocess_expression函数源码如下:(路径:src/backend/optimizer/plan/planner.c

static Node *
preprocess_expression(PlannerInfo *root, Node *expr, int kind)
{
	/*
	 * Fall out quickly if expression is empty.  This occurs often enough to
	 * be worth checking.  Note that null->null is the correct conversion for
	 * implicit-AND result format, too.
	 */
	if (expr == NULL)
		return NULL;

	/*
	 * If the query has any join RTEs, replace join alias variables with
	 * base-relation variables.  We must do this first, since any expressions
	 * we may extract from the joinaliasvars lists have not been preprocessed.
	 * For example, if we did this after sublink processing, sublinks expanded
	 * out from join aliases would not get processed.  But we can skip this in
	 * non-lateral RTE functions, VALUES lists, and TABLESAMPLE clauses, since
	 * they can't contain any Vars of the current query level.
	 */
	if (root->hasJoinRTEs &&
		!(kind == EXPRKIND_RTFUNC ||
		  kind == EXPRKIND_VALUES ||
		  kind == EXPRKIND_TABLESAMPLE ||
		  kind == EXPRKIND_TABLEFUNC))
		expr = flatten_join_alias_vars(root, expr);

	/*
	 * Simplify constant expressions.
	 *
	 * Note: an essential effect of this is to convert named-argument function
	 * calls to positional notation and insert the current actual values of
	 * any default arguments for functions.  To ensure that happens, we *must*
	 * process all expressions here.  Previous PG versions sometimes skipped
	 * const-simplification if it didn't seem worth the trouble, but we can't
	 * do that anymore.
	 *
	 * Note: this also flattens nested AND and OR expressions into N-argument
	 * form.  All processing of a qual expression after this point must be
	 * careful to maintain AND/OR flatness --- that is, do not generate a tree
	 * with AND directly under AND, nor OR directly under OR.
	 */
	expr = eval_const_expressions(root, expr);

	/*
	 * If it's a qual or havingQual, canonicalize it.
	 */
	if (kind == EXPRKIND_QUAL)
	{
		expr = (Node *) canonicalize_qual((Expr *) expr);

#ifdef OPTIMIZER_DEBUG
		printf("After canonicalize_qual()\n");
		pprint(expr);
#endif
	}

	/* Expand SubLinks to SubPlans */
	if (root->parse->hasSubLinks)
		expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL));

	/*
	 * XXX do not insert anything here unless you have grokked the comments in
	 * SS_replace_correlation_vars ...
	 */

	/* Replace uplevel vars with Param nodes (this IS possible in VALUES) */
	if (root->query_level > 1)
		expr = SS_replace_correlation_vars(root, expr);

	/*
	 * If it's a qual or havingQual, convert it to implicit-AND format. (We
	 * don't want to do this before eval_const_expressions, since the latter
	 * would be unable to simplify a top-level AND correctly. Also,
	 * SS_process_sublinks expects explicit-AND format.)
	 */
	if (kind == EXPRKIND_QUAL)
		expr = (Node *) make_ands_implicit((Expr *) expr);

	return expr;
}

preprocess_expression中涉及的函数功能介绍:

函数名作用
flatten_join_alias_vars用基本关系变量取代连接别名变量
eval_const_expressions进行常量表达式的简化
canonicalize_qual对表达式进行规范化

预处理HAVING子句

  在查询规划中,预处理HAVING子句是指对查询的HAVING条件进行处理和转换,以便为后续优化和执行过程做准备。HAVING子句用于在GROUP BY聚合后对结果集进行过滤,类似于WHERE子句,但是作用于分组后的结果。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/783238.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络教程】如何快速的解决WordPress“另一更新正在进行”的问题

文章目录 WordPress提示“另一更新正在进行”解决方案手动删除数据库记录使用插件WordPress提示“另一更新正在进行” 当我们在更新WordPress的插件或者升级WordPress时会出现后台提示“另一更新正在进行”,如下图 当我们点击更新后,出现下图提示 出现上述问题是由于在升级Wo…

瑞吉外卖开发笔记 七(redis、Spring Cache)

缓存优化 问题说明 用户数量多&#xff0c;系统访问量大频繁访问数据库&#xff0c;系统性能下降&#xff0c;用户体验差 环境搭建 maven坐标 在项目的pom.xm1文件中导入spring data redis的maven坐标: <dependency> <groupId>org.springframework.boot</g…

【Hello mysql】 mysql的视图

Mysql专栏&#xff1a;Mysql 本篇博客简介&#xff1a;介绍mysql的视图 介绍mysql的视图 基本概念基本使用创建视图修改视图删除视图 视图规则和限制总结 基本概念 视图是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数…

基于帧差法和形态学处理的行驶车辆跟踪算法matlab仿真

目录 1.算法理论概述 2.部分核心程序 3.算法运行软件版本 4.算法运行效果图预览 5.算法完整程序工程 1.算法理论概述 车辆跟踪是计算机视觉领域中的一个重要问题&#xff0c;它在交通监控、智能交通系统、自动驾驶等领域具有广泛的应用。本文介绍一种基于帧差法和形态学处…

maven安装配置、命令

maven: 是一个apache的一个开源项目&#xff0c;是一个项目管理工具&#xff0c;用来帮助开发者管理项目中的 jar&#xff08;mysql&#xff0c;jaskson&#xff0c;jwt&#xff09;&#xff0c;以及 jar 之间的依赖关系、完成项目的编译、测试、打包和发布等工作。 为什么学习…

WEB:wife_wife

背景知识 JavaScript原型链污染 题目 先尝试一下&#xff0c;注册了管理员账号 这里不知道邀请码&#xff0c;所以没有勾选 答案不正确 这里借鉴其他大佬的思路 查看源代码才知道&#xff0c;后端没有数据库&#xff0c;所以sql注入是不可能的 // post请求的路径 app.pos…

Python open()函数之buffering缓冲区策略

文章目录 一、buffering 缓冲策略二、示例1. 可交互文本文件1.1 buffering-1&#xff0c;行缓冲&#xff08;默认&#xff09;1.2 buffering0&#xff0c;文本模式不支持关闭缓冲区1.3 buffering1&#xff0c;行缓冲&#xff0c;同 buffering-11.4 buffering>1&#xff0c;i…

使用开源项目并使用docker的方式搭建代理接口

目录 一、docker部署代理池子测试1、windows搭建代理池子测试2、linux上搭建代理池子测试 一、docker部署代理池子测试 这里使用的代理池子项目是崔大的git开源的项目&#xff0c;代理项目代码这里选择的安装方式是docker安装&#xff0c;这样即使本地没有redis环境&#xff0…

linux 在excel里面找内容

linux 在excel里面找内容 背景&#xff1a;在大数据行业中&#xff0c;很多数据源是excel文件&#xff0c;但是常常会出现查找excel内容找到对应的文件&#xff0c;所以制作了简单的shell脚本方便查询对应的excel文件 查看下面精简的内容即可&#xff0c;开箱即用 shell转换 …

python web开发之gunicorn 和 uWSGI 对比和配置

关于uWSGI的定义&#xff0c;在上一篇文章中写了&#xff0c;链接&#xff1a;WSGI/uwsgi/uWSGI详解 python开发常见的容器就只有的uWSGI和Gunicorn&#xff0c;本文介绍两者的区别和配置 1. 共同点 在架构上&#xff0c;nginx负责动态的转发和静态文件的直接访问&#xff0c;…

三、万物皆对象(2)

本章概要 类的创建 类型字段基本类型默认值方法使用 返回类型参数列表 程序编写 命名可见性使用其他组件static 关键字 小试牛刀 编译和运行 编码风格 类的创建 类型 如果一切都是对象&#xff0c;那么是什么决定了某一类对象的外观和行为呢&#xff1f;换句话说&#xff…

2023年华数杯数学建模竞赛ABC题思路代码论文资料汇总贴

下文包含&#xff1a;2023华数杯数学建模竞赛ABC题思路解析代码参考论文等及如何准备数学建模竞赛 C君将会第一时间发布选题建议、所有题目的思路解析、相关代码、参考文献、参考论文等多项资料&#xff0c;帮助大家取得好成绩。2023华数杯数学建模竞赛于8月3号下午6点正式开赛…

Origin科学绘图分析软件2023最新版下载安装教程

在科学研究和工程领域&#xff0c;数据的处理和分析是至关重要的一环&#xff0c;而Origin则是这方面的一款重要工具。Origin软件是由OriginLab公司开发的&#xff0c;主要用于各种科学数据的处理和分析&#xff0c;以及高质量的科学图形的创建。#乐享周末分享吧# 下载地址文末…

Spring Cloud Eureka 服务发现速度慢配置优化总结

文章目录 一、 Eureka-server 服务端缓存问题1.1 服务端缓存1.2 客户端从服务端获取实例数据的过程1.3 优化 二、客户端 Eureka-client 缓存导致2.1 Eureka客户端和服务端交互缓存2.2 Ribbon 缓存了EurekaClient的缓存2.3 优化 使用Eureka时&#xff0c;常常会发现服务发现慢&a…

Stable Diffusion 本地部署教程

1.前言&#xff1a; 最近看Stable Diffusion开源了&#xff0c;据说比Disco Diffusion更快&#xff0c;于是从git上拉取了项目尝试本地部署了&#xff0c;记录分享一下过程~ 这里是官网介绍&#xff1a;https://stability.ai/blog/stable-diffusion-public-release 2.必要前提…

jar 更新 jar包内的 class,以及如何修改class

一、提取Jar 内文件 #提取jar内的配置文件jar -xvf a.jar META-INF\plugin.xml-已解压: META-INF/plugin.xml#提取jar内的class文件&#xff0c; 提示&#xff1a;反编译为java文件&#xff0c;修改后再使用javac xxx.java编译为class&#xff0c;jar -xvf a.jar io.config.**…

三维测量技术在高端精密制造中的应用

科技创新是新时代的重要发展动力。三维测量技术以精密机械为基础&#xff0c;综合应用了电子技术、计算机技术、光学技术和数控技术等先进技术&#xff0c;可以对机械、汽车、航空、家具、工具原型等测量出高精度的几何零部件以及测量复杂形状的机械零部件&#xff0c;给各行业…

Autosar IOC机制(核间通信)

文章目录 一、IOC二、诊断代码实例一、IOC IOC和操作系统紧密相关,是操作系统实现的一部分 ①ECU间通信:通过通信协议栈定义好的API进行通信,通俗来讲就是通过总线(CAN/LIN/Flexlay)进行通信。 ②OS-Application内SWC间的通信:通过RTE处理。 ③OS-Application间的通信:通信…

【iOS】自定义字体

文章目录 前言一、下载字体二、添加字体三、检查字体四、使用字体 前言 在设计App的过程中我们常常会想办法去让我们的界面变得美观&#xff0c;使用好看的字体是我们美化界面的一个方法。接下来笔者将会讲解App中添加自定义字体 一、下载字体 我们要使用自定义字体&#x…

JQuery全部过滤选择器详细介绍下

文章目录 JQuery全部过滤选择器详细介绍-下属性过滤选择器● 属性过滤选择器-应用实例代码演示 子元素过滤选择器● 子元素过滤选择器基本介绍5. nth-child() 选择器详解如下&#xff1a;● 子元素过滤选择器示例-应用实例代码演示 表单属性过滤选择器● 此选择器主要对所选择的…