《PostgreSQL指南:内幕探索》第三章笔记

本文详细阐述了数据库查询处理的全过程,包括解析器、分析器、重写器、计划器和执行器的角色和功能。解析器生成语法树,分析器进行语义分析,重写器依据规则系统改写查询,计划器生成最优执行计划,而执行器则按照计划执行查询。重点讨论了查询代价估计,如启动代价和运行代价,并举例说明了单表查询的代价估计和计划树创建。此外,还介绍了如何在多种访问路径中选择代价最小的路径以优化查询性能。
摘要由CSDN通过智能技术生成

第三章 查询处理

主要是前面两个部分

第一部分就是简历介绍整个查询处理的流程

第二部分就是实现查询最优执行计划的步骤,这里会用单表查询作为一个非常简单的例子。分3小节讨论

第三部分,以一个更复杂的例子去讨论,多表查询。

3.1 概览

解析器(Parser)

分析器(Analyzer)

重写器(Rewriter)

计划器(Planner)

执行器(Executor)

3.1.1 解析器(Parser)

(对应着编译原理的词法分析、语法分析)
解析器基于SQL语句的文本,生成一颗后续子系统可以理解的语法解析树。

基于SQL语句的文本,首先经过词法分析,语法分析,最后生成一棵树。

两个点需要注意的:
1、解析过程时只负责在生成这棵语法树时,判断是否出现语法错误,比如这的语句是正确的,把语句里的data去掉后,这句语句可以通过词法分析,但不能通过语法分析了

2、如果查询中包含一个不存在的表名,解析器并不会报错,语义检查由分析器负责。比如我from tbl_b,如果根本没有这个表,但解析操作一样不会报错,这个由分析器负责。

3.1.2 分析器

(语义分析)
分析器对解析器产出的语法解析树(parse tree)进行语义分析,并产出一颗查询树(query tree),可以看到丰富了很多信息,并且会分析语义是否会出现问题。

到这里,生成查询树的过程和编译原理前三步基本一致,就是根据输入的SQL语句,生成一颗树,以便于后面继续处理。为了加快运行的效率,接下来就是数据库查询编译中额外的操作,以便对这颗树进行优化。

3.1.3 重写器

重写器按照规则系统中存在的规则,对查询树进行改写。

查询重写模块使用规则系统判断是否要对查询树进行重写。如果查询树中每个对象(或者说目标)被定义了转换规则,那么程序就会使用该规则重写查询树。

3.1.4 计划器

这一步其实就是对应(中间代码生成及代码优化这两步)
计划器基于上面重写得到的查询树,生成一颗执行效率最高的计划树(plan tree)。

要评价执行效率如何最高,会根据实际情况定义一个代价估计,后面会用到单表查询这个经典例子去设计一个代价估计函数。
结合例子来讲的话,好理解。

3.1.5 执行器

执行器按照计划树中的顺序访问表和索引,执行相应查询。

其实就包括编译原理的后面两步,生成目标机器语言,然后执行,当然,这一步也会设计到并行进程内存访问冲突的问题,这里师兄前面有介绍了第五章的并发控制机制。

到这里,其实重点很明显了,编译原理重点学的内容都不是重点,比如解析器、分析器、执行器,然后重写器这里可以设计一些具体的规则系统。

所以我们接下来的重点就是这个计划器,如何对这颗查询树进行优化,大家在接下来的例子抓住这个重点就好。

规则系统的定义:它修改查询为了去考虑规则,然后将修改后的查询传递给查询规划器进行规划和执行。它非常强大,可以用于许多事情,如查询语言过程、视图和版本。

计划树两个重点:代价估计,如何创建最小代价花费的计划树

3.2 单表查询的代价估计

所有被执行器执行的操作都有着相应的代价函数。所以代价函数是会根据不同的语句去专门设计对应的代价估计函数

在PostgreSQL中有三种代价:启动(start-up) , 运行(run)和总和(total)。总代价是启动代价和运行代价的和;因此只有启动代价和运行代价是单独估计的。

启动代价(start-up):在读取到第一条元组前花费的代价,比如索引扫描节点的启动代价就是读取目标表的索引页,取到第一个元组的代价

直接读表的话,启动代价就是0啦

运行代价(run): 获取全部元组的代价
总代价(total):前两者之和

在第4行显示了顺序扫描的相关信息。代价部分包含了两个值:0.00和145.00。在本例中,启动代价和总代价分别为0.00和145.00。

3.2.1 顺序扫描

来个简单的例子,看一下代价怎么算的

在顺序扫描中,启动代价等于0,运行代价由以下公式定义,比较乱,大致看看就好,里面有三个参数,分别序列页面花费,cpu元组花费、操作花费

序列页面花费 : 对磁盘页提取成本的估计
cpu元组花费 ;对查询期间处理每一行的成本的估计。默认值为0.01
操作花费:在查询期间执行的每个操作符或函数的处理成本的估计

这里其实就是根据不同量纲给他们设计了几个默认值,比如这个获取磁盘页得从存储介质中获取,那就比较慢,他的花费就远远大于另外两个。

举个例子。获取第45页,第10000行的数据。

其实这里就理解这个代价如何估计了,后面两个例子,大家也可以看看。

3.2.2 跳过

3.2.3 跳过

3.3 创建单表查询的计划树

计划器非常复杂,故本节仅描述最简单的情况,即单表查询的计划树创建过程。

PostgreSQL中的计划器会执行三个处理步骤:

1、执行预处理
2、在所有可能的访问路径中,找出代价最小的访问路径
3、按照代价最小的路径,创建计划树

3.3.1 预处理

这些都是代码优化学过的

3.3.2 找出代价最小的访问路径

分4步去说

直接上例子
这个语句的路径选择其实就只有两种可能嘛
第一种:先判断大小再排序
第二种:先排序再判断大小

评估完路径后就得到了最优路径的计划树,这里就是先排序再判断大小的代价最小嘛,也就是时间快。

3.3.3 创建计划树

这里就都是设计代码操作,结合源码看吧

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wujiekd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值