PBE协议

背景与概念

我们已经了解了一个SQL的执行,经历了parse、analyze、rewrite、plan、execute的全流程。那么思考一下,假如有一条sql语句,这条语句会执行几千次几万次,每一次都需要完整的执行上述的所有流程么?很明显,不用。
对于parse部分,同一条sql,执行千万遍,每次的parsetree也都是相同的,因此完全可以只执行一次就够了,将parsetree保存下来,之后就可以直接用了。
对于analyze、rewrite部分,如果没有执行ddl语句去修改SQL用到的表的元数据信息,那么其实也可以执行一次。
对于plan部分,可能受到的影响大一些,DDL、表数据量发生大量变化的时候,都有可能会导致计划发生变化,但在通常的TP场景情况下这种可能性不大。
对于execute部分,这部分理论上就不是十分的方便复用了,因为每一次写操作都可能导致一条sql的结果发生变化。

因此我们可不可以思考一种方案,对于这些重复执行的SQL的每个环节抽象出来,将parsetree、querytree、plan等可以复用的东西,在第一次执行的时候保存下来,之后执行的取出来直接使用,这样不就可以省略下来一大串的流程,提高性能了吗!当然对于一些部分,我们肯定也需要那么一套机制让这些保存下来的东西,在执行了DDL等场景之后失效掉。

但是在实际中,一条完全相同的SQL重复执行多遍的场景有,但是更多的是另一种场景,SQL的结构完全相同,但只是其中的某几个数值不同。例如学生根据自己的学号查询信息,会用到这么一条语句:select * from students where id = ?;每一个学生都会用这条语句,但每个学生的学号都不相同。

对于这种情况,我们可以考虑一种方案,在生成计划的时候,将这些会变得数值以参数的形式替代,之后每次调用查询的时候,先根据语句中的数值将计划中的参数补充完整,之后再去执行,也可以省下来大把的流程时间。
说到这里聪明的大家应该已经想到了pg中的prepare-execute语法,或者java中的preparedStatement接口。没错,就是他们,这种执行方式在数据库内核中对应的名称就是PBE。

按照我们所预想的方案,其所对应的环节可以分为三个:
P(parse),解析SQL语句,生成parsetree、querytree并保存起来。
B(bind),若是第一次调用则生成并保存计划,若已有计划则直接找出来使用,若计划需要参数则将参数补充完整。
E(execute),根据已经完整的计划去执行。

方案实现

数据结构

分析可知,我们在会话的范围内需要有一个用来存储各种计划的位置,需要有一些数据结构用来描述保存的语句、保存的各种tree、保存的plan、参数描述等。
因此按照如下方式进行组织:

PreparedStatement NodeTag node char* sqlstr int len CachedPlanSource psrc ... CachedPlanSource Node* raw_parse_tree; int num_params List* query_list; CachedPlan* gplan; CachedPlan* cplan; ... CachedPlan List* stmt_list; bool dependsOnRole ...

preparedStatement结构抽象表示保存的准备语句,并存在在会话级别的哈希表xxx中,preparedStatement中的name、sqlstr、len等存储一条准备语句最基本的信息,CachedPlanSource psrc用来存储计划缓存的所有东西,包括parsetree、querytree、plan、参数信息等等。

在CachedPlanSource中,raw_parse_tree存储parsetree,query_list存储querytree。但是其计划并非直接存储,而是额外封装了一层CachedPlan表示,但是我们发现其有两个,cplan和gplan,这两个分别表示不带参数的常规计划(custom plan)和带参数的模板计划(generic plan)。另外其所携带的参数数量、参数列表、有效性标志等等,还有很多东西,都存在这个结构体中,它相当于就是优化器产生和需要的所有东西,都在这里了。

CachedPlan中,stmt_list中存储的便是计划树了。

当然以上只是比较重要的骨架部分,还有很多实现的细节,以及各种场景各种特性所涉及到的东西,例如GPC相关的等等。

P阶段

p阶段主要是用来解析SQL语句,生成parsetree、querytree并保存起来。
流程大致:

1、检查会话之中是否已经存在同名的准备语句
2、根据sql的name、sql内容创建一个PreparedStatement结构,存入会话之中
3、创建CachedPlanSource,完善PreparedStatement
4、进行词法语法解析,生成parsetree,填入完善CachedPlanSource
5、进行语义分析和重写,生成querytree,填入完善CachedPlanSource

在这些步骤中,我们需要考虑带参数的情况,好在查询编译器已经支持接收带参数的输入,并生成对应的带参分析树查询树等,因此这里不再进行赘述其细节。

B阶段

B(bind),若是第一次调用则生成并保存计划,若已有计划则直接找出来使用,若计划需要参数则将参数补充完整。
当然B阶段需要做的不仅这么简单,我们还需要去提前校验已经保存的计划是不是失效了。

首先从输入输出的角度分析B阶段:
输入:所执行的准备语句的各种数据(CachedPlanSource)、本次执行的参数
输出:完整的执行计划。

大致流程如下:
1、根据name等,找出来会话中存放的对应的PreparedStatement结构。
2、验证其中的CachedPlanSource psrc是否已经失效,如果是,则重新生成一个,如果有效则直接使用即可。
3、如果是有参数的,则根据psrc中的参数信息,预处理本次输入的参数,处理成便于我们绑定和使用的格式。如果没有则不需要此步骤。
4、如果psrc内已经有计划(cplan or gplan),则检查计划是否已经失效。如果是,则删除特。
5、判断本次执行所需要的计划类型是cplan还是gplan
6、若已经有计划,但是与本次所需类型不符合,则删除特。
7、到此我们无论如何都已经有一个符合要求的计划了,如果需要参数的话,则绑定步骤3中处理好的参数。
8、到此已经有一个完整的计划了。

E阶段

E阶段就简单了起来,计划也有了,也是完整的,执行就完事了。

失效清理

计划失效一般存在于执行了DDL语句,例如修改了表结构、增删了索引等,都会导致计划发生变化、失效。
失效清理存在于两种场景,第一种是自身会话执行了DDL导致自身的缓存计划失效,第二种是别的会话执行了DDL导致自身的缓存计划失效。

实际使用场景

我们已经知道了PBE是在数据库内部如何实现的,那么我们应该怎么去使用呢?常见的场景主要有两个,一个是通过prepare-execute语法,一个是通过jdbc、odbc等的驱动接口使用。
对于这两种场景,实际上都是对上面代码实现的各个模块进行了各自的封装而已。

prepare-execute语法

prepare-execute语法,例如

prepare query1(int) as select * from students where id = $1;
execute query1(123456);
execute query1(234567);
....

通过p-e语法来使用PBE,数据库内部逻辑比较简单。
prepare语句的执行,对应的是P阶段,其在数据库内核中的实现接口为ExecPrepare函数。
execute语句的执行,对应的是BE阶段,其在数据库内核中的接口对应ExecuteQuery函数。

报文驱动接口

最常见的方式就是使用JDBC驱动,调用里面的preparedStatement接口来使用。
jdbc客户端与数据库通信的方式是使用报文的方式。因此我们需要了解jdbc每个接口所发送的报文,数据库对于每条报文都是怎么处理的。

// 会在jdbc客户端驱动的缓冲区内拼装一条报文,格式如:
// Q len ... sql ...
// 主要有Q报文头,报文长度len,查询语句内容,还有一些jdbc为这条SQL生成的名称之类的。
p1.preparedStatement("select * from stduents where id = ?");

// 会在jdbc客户端驱动的缓冲区内追加一条报文
// B len len1 param1 ....
// 主要有B报文头,报文长度len,以及每个参数。
p1.bindint(1,123456);

// 会在jdbc客户端驱动的缓冲区中追加一条报文
// E len ...
// 之后会将缓冲区中的三条报文一起发送给数据库服务器
p1.execute()


// 之后只需要发送B与E报文即可,因为parse部分只需要执行一遍。

其对应的处理报文的函数分别为:
exec_parse_message()
exec_bind_message()
exec_execute_message()
三个函数与上一章节所述的实现PBE阶段完全对应,因此在这里不在赘述。

代码实现

以exec_parse_message()、exec_bind_message()、exec_execute_message()三个函数为例子:

JDBC接口的更多操作

通过上一节我们已经知道了jdbc的方式的基础原理,那么在jdbc之中我们还有很多的操作,例如fetch、batch等操作。这些操作对应的实现方式:

batch

功能为每次返回一批数据,这样可以防止结果数据量太大,一次全部返回导致客户端内存不够。
因此数据库内

fetch

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: VASP是一种常用的第一性原理计算软件,用于研究材料的电子结构和性质。在VASP中,使用赝势方法可以减少计算复杂度,提高计算效率。 赝势(pseudopotential)是一种通过与核心电子相互作用模拟全电子系统行为的方法。赝势文件中的PAW (Projected Augmented Wave)和PBE (Perdew-Burke-Ernzerhof)表示VASP计算中的两个重要参数。 PAW是一种将全电子波函数转换为缀加波(expansion)的方法。在PAW中,通过选择合适的投影函数,将核心电子的电子密度投影到虚拟平面上,同时用缀加波函数描述残余的电子态。PAW方法能够显著提高计算效率,同时准确保留了核心电子贡献。 PBE是一种广泛应用的交换-相关泛函。在VASP中,PBE泛函用于计算电子之间的交换和相关作用,从而确定材料的电子结构和性质。PBE泛函基于密度泛函理论,计算精度较高,适用于各种材料的研究。 VASP赝势文件中的PAW和PBE参数,代表了在计算中使用的赝势方法和泛函选择。通过合理设置这些参数,我们可以在VASP中进行高效准确的电子结构计算,研究材料的能带结构、态密度、电荷密度等性质,为理解和设计材料的功能奠定基础。 ### 回答2: VASP(Vienna Ab initio Simulation Package)是一种材料计算软件,用于通过第一性原理计算方法计算材料的物理和化学性质。赝势(Pseudopotential)是VASP中常用的方法之一,用于减小计算中在原子核附近陡峭变化的电子波函数。赝势文件是赝势方法计算中所需的输入文件,其中"PBE"是指采用“PBE”(Perdew-Burke-Ernzerhof)密度泛函理论作为交换相关泛函的基准。 PBE是一种常用的密度泛函理论方法,用于描述材料中电子的行为。它是基于局域密度逼近的原理,通过引入交换和相关泛函修正了LDA(局域密度近似)的不足。PBE方法比LDA更准确,可以更好地预测材料的结构、能带结构、能量和电子性质等。 对于VASP中的赝势方法,PAW(Projector Augmented Wave)是一种常用的赝势方法,它在计算中考虑了原子核附近的电子波函数的详细信息,并引入了一组投影算符来描述电子与原子核的相互作用。PAW赝势可以准确描述电子的行为,计算结果更可靠。 因此,VASP赝势文件paw pbe是用于赝势计算的输入文件,其中paw表示使用PAW赝势,pbe表示采用PBE密度泛函理论作为基准。通过使用这样的赝势文件,我们可以在VASP中进行准确可靠的密度泛函计算,得到材料的各种物理和化学性质的预测结果。 ### 回答3: VASP赝势文件PAW是一种计算物质性质的常用工具,常用于第一原理计算中。PAW代表赝原子波函数(Projector Augmented Wave),PBE代表泛函近似Perdew-Burke-Ernzerhof。 在VASP赝势文件中,PAW方法通过引入赝原子波函数来处理波函数的计算。原子核和赝原子核分别作用于真实的电子波函数和赝波函数,从而实现对真实系统的模拟。PAW方法有效地解决了真实电子波函数与计算中使用的平面波基组之间的不匹配问题。 而PBE泛函是一种基于密度泛函理论的交换-相关能密度泛函,用于近似交换-相关能的计算。PBE泛函广泛应用于材料科学、化学和物理等领域的密度泛函理论计算中。它能够较好地描述材料的结构、能量、电子结构和电子态密度等性质。 在VASP赝势文件中,PAW PBE是同时使用PAW方法和PBE泛函进行计算。将PAW和PBE相结合,可以更准确地描述原子和分子体系的性质。PAW方法解决了赝波函数与真实波函数不匹配的问题,而PBE泛函考虑了交换-相关能的影响,两者的结合可以更精确地描述材料的能带结构、电荷密度分布等性质。 总而言之,VASP赝势文件PAW PBE结合了PAW方法和PBE泛函,可用于模拟材料的电子结构和性质,具有较高的准确性和可靠性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值