终于要迎来postgresql的《A Tour of PostgreSQL Internals》系列的最后一篇了。学习是不能拖延的事儿,越拖延事情越多。不废话,一起来看看吧~

View 3 Postgresql的查询处理

       还是先上图吧。下面这张图从整体上概括了Postgresql的查询处理的步骤以及牵涉到的各个模块。



       其中最重要的关键的两个数据结构是查询分析树(parse tree),和查询计划树(plan tree)。

       对上图所标示的四个模块,下面一一来分析。


3.1 Parser(查询分析模块)

该模块通过对SQL语句进行分析生成查询树。

       查询分析是查询编译的第一个模块,包括词法分析、语法分析和语义分析。它将用户输入的SQL语句进行词法分析(使用Lex工具)和语法分析(Yacc工具)生成分析树,然后进行语义分析得到查询树(parse tree)。

查询树中有几个重要的属性:

1) commandType:查询树对应的命令类型,说明由哪类命令生成该查询树。包括CMD_SELECT、CMD_DELETE、CMD_UPDATE、CMD_INSERT和CMD_UTILITY,如果命令类型为CMD_UTILITY,则查询优化器不会对该查询树进行优化。

2) rtable:范围表,查询中使用的表的列表。

3) resultRelation:结果关系,是涉及数据修改的范围表,该字段只适合INSERT/UPDATE/DELETE命令。

4) targetList:表示目标属性,用于存放查询结构属性的表达式,分四种情况:

a.SELECT语句:目标属性即为SELECT和FROM之间的表达式;

b.DELETE语句:不需要目标属性,因为DELETE语句不返回元组;

c.INSERT语句:目标属性描述插入到结果关系的元组的属性;

d.UPDATE语句:目标属性描述被更新的属性,即SET子句中的属性。

5) jointree:连接树,查询的连接树显示了FROM子句中表的连接情况,通常还会附加上WHERE的条件表达式。

比如有如下的SQL语句:

SELECT * FROM tab1, tab2 WHERE tab1.a = tab2.f

那么该语句的查询树如下:

3.2 Rewriter(重写模块)

对查询树重写并生成新的查询树,以提供对规则和视图的支持。

       查询重写模块使用规则系统判断来进行查询树的重写,如果查询树中的某个目标被定义了转换规则,则该转换规则会被用来重写查询树。

       例如:如果3.1中提到的tab2是一个视图,则该视图会被替换为一个对应的子查询。重写模块将会生成一个新的查询树。如下图所示:

       查询重写的核心是规则系统。而规则系统由一系列的规则组成。系统表pg_rewrite中存储了重写规则。

       根据系统表pg_rewrite的不同属性,规则可以按两种方式分类:

  • 按照规则使用的命令类型:可分成SELECT、UPDATE、INSERT和DELETE四种;
  • 按照规则执行动作的方式:可分为INSTEAD(替代)规则和ALSO规则。

       在插入/更新/删除时规则需要更复杂的转换,并且可能从一个查询中产生多个查询。

3.3 Planner(查询计划模块)

本模块的主要功能是对给定的SQL查询语句,基于代价估计模型,选择最优的查询计划树。

       SQL语句不同于JAVA,C语言这样,编写好之后按照固定的顺序和路径执行,相反,SQL只指明要求的查询结果,没有指定具体的查询路线。因此,在数据库管理系统中,用户的请求查询可以用不同的方案来执行。尽管执行结果是相同的,但是执行效率却存在差异。查询计划就用于选择一种代价最小的方案。因此,在数据库查询性能方面起着举足轻重的作用。

举例说明,假如有如下的SQL语句:

SELECT * FROM t WHERE f1 < 100;

我们假设在t(f1)上建立了索引。那么我们就可能有两种可能的查询计划:

1.顺序地扫描全表(Full table scan);
2.利用索引t(f1)查找 f1 < 100 的元组(Index scan);

查询计划就会计算时间代价(磁盘页的读取和CPU时间),然后选择时间代价较少的查询计划。

虽然大多数情况下,Index scan 会比 Full table scan 要快一些,但是这并非必然。这还和被检索的行数有关,这个问题在此处就不展开了。

3.4 Executor(执行模块)

执行模块的基本工作是执行一个查询计划树。

       一个查询计划树的执行是一个像流水线一样对节点进行处理的网络。每次被调用时,每个节点将产生的元组放在它的输出序列中。上层节点调用下层子节点获取输入元组,利用这些输入元组计算本节点的输出元组。对于这些节点,有以下区别:

       1) 底层节点直接对物理表进行扫描,要么是全表扫描,要么是通过索引扫描(index scan);

       2) 上层节点主要是进行join(nested-loop, merge, hash join)操作的节点;

       3) 当然,也有特殊用途的节点类型,如用于排序和聚合。

听起来很绕,我们看个例子。

对于下面的SQL语句:

SELECT SUM(a1)+1 FROM a WHERE a2 < a3;

模块执行的查询计划树如下图:

再来一个两表之间join+聚集函数例子:

SELECT DISTINCT a1, b1 FROM a, b WHERE a2 = b2 AND a3 = 42;

对应的查询计划树如下图:

3.5 和join相关的查询计划

       在多表(表的个数为n)查询的情形下,查询计划首先估算每个表分别采用Index scan(如果有的话) 和Full table scan的查询代价,然后建立一个join的树型结构,在树中包括了每一对两两连接的路径。这样,在树的第k层给出k个表执行join的最小代价的执行方式,那么递归地,在顶层(第n层)获得执行这n个表join操作的最佳查询方式。至此,就获得了查询n个表join操作的查询计划。

       当然,我们不得不考虑的是,由于搜索最佳join方式的代价呈指数式上升,当参与join的表很多时(例如,超过10个),彻底地全局搜索最优join组合的代价会变得很大导致显著地降低系统性能。因此,我们退而求其次,使用概率搜索算法来代替全局搜索。这里,postgresql使用的是遗传算法。

3.6 non-SELECT语句的执行

       什么是non-SELECT语句?简而言之,就是INSERT、UPDATE和DELETE语句。

       1) 对于INSERT语句来说,其基本过程和SELECT语句是相似的,只不过最后的查询结果行不是返回到查询端,而是插入到表中;

       2) 对于UPDATE/DELETE语句来说,查询计划模块会使用查询树的targetList项来存储选中的行,targetList项会被返回给executor模块的顶层来决定哪些行要被update/delete。

       所以我们可以看出,对于查询计划模块和executor的大部分来说,所有的查询语句看起来都像是SELECT。只有顶层的executor会根据查询类型的不同有不同的操作。


小结

说了这么多,该总结一下了。对于postgresql的查询处理模块评价如下:

优点:

  • 显而易见,系统可以自己分析决定去选择一个好的查询计划,而不需要人工协助。

缺点:

  • 我们评价一个查询计划的好坏是基于系统的代价计算模型和历史的统计数据,代价计算模型本身不可能尽善尽美,有其自身的缺陷;再者,历史数据可能有时也不那么可靠。

  • 凡事都有代价,生成一个查询计划也是要花费时间的。因此对一个频繁的重复查询而言,生成的查询计划的时间代价就会比较大。

以上就是《A Tour of PostgreSQL Internals》系列的全部内容了,欢迎大家讨论,有不对的地方还请各位批评指正。

对了,本篇随笔还参考了《PostgreSQl数据库内核分析》一书,在此对书的作者表示感谢,有兴趣的朋友可以查看这本书查看详细的解释与分析。

终于,《A Tour of PostgreSQL Internals》系列到此就要完结了,欠的债终于还清了,下面该干嘛?前面还有好多坑等我去填呢~

以上です

《A Tour of PostgreSQL Internals》学习笔记——查询处理分析的更多相关文章

  1. 《A Tour of PostgreSQL Internals》学习笔记——进程间通信

    中秋节假期这么快就没了,这几天还一直下雨,索性在家看看书.这次看的是Tom Lane的<A Tour of PostgreSQL Internals>.这篇小随笔就算做学习笔记了.园子里面 ...

  2. 《A Tour of PostgreSQL Internals》学习笔记——系统表和数据类型

    上周末学习了<A Tour of PostgreSQL Internals>的第一部分(View 1),今天我们继续打开书本,继续View 2 部分. View 2 Postgresql的 ...

  3. 【转】MongoDB学习笔记(查询)

    原文地址 MongoDB学习笔记(查询) 基本查询: 构造查询数据. > db.test.findOne() { "_id" : ObjectId("4fd58ec ...

  4. UML和模式应用学习笔记-1(面向对象分析和设计)

    UML和模式应用学习笔记-1(面向对象分析和设计) 而只是对情节的记录:此处的用例场景为:游戏者请求掷骰子.系统展示结果:如果骰子的总点数是7,则游戏者赢得游戏,否则为输 (2)定义领域模型:在领域模 ...

  5. ArcGIS案例学习笔记4_2_水文分析批处理地理建模

    ArcGIS案例学习笔记4_2_水文分析批处理地理建模 联系方式:谢老师,135_4855_4328,xiexiaokui#139.com 概述 计划时间:第4天下午 目的:自动化,批量化,批处理,提 ...

  6. ArcGIS案例学习笔记4_1_水文分析

    ArcGIS案例学习笔记4_1_水文分析 联系方式:谢老师,135_4855_4328,xiexiaokui#139.com 概述 计划时间:第4天上午 教程: pdf page478 数据:实验数据 ...

  7. Mysql与PostgreSql数据库学习笔记---打酱油的日子

    mysql 从最基础的数据引擎,到进程结构,都不能支持数据版本.导致其职能阻塞“并发”,不支持最基本的事务,innodb达不到基本事务要求,任何写数据,都导致整个表锁住.充其量只能算是一个玩具,或者说 ...

  8. PostgreSQL内核学习笔记四(SQL引擎)

    PostgreSQL实现了SQL Standard2011的大部分内容,SQL处理是数据库中非常复杂的一部分内容. 本文简要介绍了SQL处理的相关内容. 简要介绍 SQL文的处理分为以下几个部分: P ...

  9. PostgreSQL内核学习笔记十一(索引)

    Index Scan涉及到两部分的内容Heap Only Tuple和index-only-scan. 什么是Heap Only Tuple(HOT)? 例如:Update a Row Without ...

随机推荐

  1. ThinkPHP简单结构介绍!

    thinkPHP简单结构介绍: application : 应用 extend:扩展 扩展内库 public:入口文件 index.php 在里面 runtime:缓存文件(里面的文件可以随便删除) ...

  2. SVN常见问题及解决方法(转载)

    svn常见符号 黄色感叹号(有冲突):--这是有冲突了,冲突就是说你对某个文件进行了修改,别人也对这个文件进行了修改,别人抢在你提交之前先提交了,这时你再提交就会被提示发生冲突,而不允许你提交,防止你 ...

  3. Oracle之使用rman进行异机恢复测试记录

    本次测试目的是从生产数据库导出rman备份然后在测试数据库恢复 1,拷贝备份至相应目录 2,进入rman rman target \ 3,关闭数据库 shutdown 4,以nomount模式启动数据 ...

  4. angular-translate国际化

    1.<h1>{{"hello" | translate}}</h1>2.<h1 ng-bind-html="'hello' | transl ...

  5. Oracle管理监控之段空间利用监控-oracle性能优化

    SELECT S.OWNER,       S.SEGMENT_NAME,       S.SEGMENT_TYPE,       S.PARTITION_NAME,       ROUND(BYTE ...

  6. php安装xmlwriter遇到报错及解决方法

    Q1:make的时候报' error: 'zend_class_entry' has no member named 'default_properties''错误, A:把 错误行C文件中defau ...

  7. PHP通过curl模拟POST上传文件,5.5之前和之后的区别

    首先先要着重提一下,只要是做和项目有关的开发,首先按把环境中各个服务的版本保持一致,否则出些莫名其妙的错我,让你百爪挠心却不知哪里的问题.这里就要说下curl_setopt($ch, CURLOPT_ ...

  8. Drawing Graphs using Dot and Graphviz

    Drawing Graphs using Dot and Graphviz Table of Contents 1. License 2. Introduction 2.1. What is DOT? ...

  9. Disruptor的伪共享解决方案

    1.术语 术语 英文单词 描述 内存屏障 Memory Barriers 是一组处理器指令,用于实现对内存操作的顺序限制. In the Java Memory Model a volatile fi ...

  10. MVC模式:python案例

    quotes = ('A man is not complete until he is married. Then he is finished.', 'As I said before, I ne ...