Postgresql Executor 阶段内存结构
来源:互联网 发布:手机淘宝怎么投诉卖家 编辑:程序博客网 时间:2024/04/30 04:54
Postgresql Executor 阶段内存结构
|||
上次写完了postgresql中plantree内存结构后,接下来就是执行器阶段了,首先我们得重申我们的前提条件:
假定我们数据库中已经有如下表,并填充了数据:
CREATE TABLE pois
(
uid integer not null,
catcode VARCHAR(32) not null,
);
现在我们用psql发送请求:select catcode from pois;
程序已经执行完了stmt = (Node *) pg_plan_query(query, cursorOptions, boundParams);了。
我们来看看接下来需要执行的函数调用:
我们先来看/backend/executor/exeMain.c中的注释,然后分别对上面的调用分析。
The old ExecutorMain() has been replaced by ExecutorStart(),ExecutorRun() and ExecutorEnd()
These three procedures are the external interfaces to the executor.In each case, the query descriptor is required as an argument.
ExecutorStart() must be called at the beginning of execution of any query plan and ExecutorEnd() should always be called at the end of execution of a plan.
看样子ExecutorStart(),ExecutorRun() and ExecutorEnd()贯穿整个executor的全过程。
1.portal = CreatePortal("", true, true);
是创建一个名字为“”的portal,创建之后如下图,并插入到PortalHashTable的hash表中:
2.PortalDefineQuery(portal,
NULL,
query_string,
commandTag,
plantree_list,
NULL);
该函数只是对上面的portal进行进一步的初始化,比较重要的一个赋值是:portal->stmts=plantree_list.
赋值完之后如下图:
3.PortalStart(portal, NULL, InvalidSnapshot);
其中最主要的调用是 InitPlan() ,调用堆栈是:
postgresql Thread [C/C++ Attach to Application]
gdb Debugger (5/1/10 10:16 AM) (Suspended)
Thread [1] (Suspended)
10 InitPlan() /home/postgres/develop/.../src/backend/executor/execMain.c:649
9 standard_ExecutorStart() /home/postgres/develop/.../src/backend/executor/execMain.c:219
8 PortalStart() /home/postgres/develop/.../src/backend/tcop/pquery.c:539
7 exec_simple_query() /home/postgres/develop/.../src/backend/tcop/postgres.c:953
6 PostgresMain() /home/postgres/develop/.../src/backend/tcop/postgres.c:3617
5 BackendRun() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:3449
4 BackendStartup() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:3063
3 ServerLoop() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:1387
2 PostmasterMain() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:1040
1 main() /home/postgres/develop/.../src/backend/main/main.c:188 0x081e7ee7
到此为止,我们形成的数据结构有些庞大了,如下图(有谁能告诉我哪儿能上传大图的?picasa不行,flickr不行):
更清晰的全图可以从这里下载。
但是有几个重要的可以罗列一下,可以号称3大天王:
4.PortalSetResultFormat(portal, 1, &format);
该函数的主要作用是格式化输出字段。共有natt=1,格式化赋为0,0默认为输出为text。如源码中的注释:
format = 0; /* TEXT is default */
5.receiver = CreateDestReceiver(dest);
6.SetRemoteDestReceiverParams(receiver, portal);
其中dest=DestRemote
这一个阶段比较简单,最终形成的数据结构为(图中做了简化,但不影响理解):
7.(void) PortalRun(portal,
FETCH_ALL,
isTopLevel,
receiver,
receiver,
completionTag);
千辛万苦终于到了portalrun了。
顺序抽取tuple的主循环是ExecutePlan() ,调用堆栈为:
gdb Debugger (5/2/10 5:14 PM) (Suspended)
Thread [1] (Suspended)
11 ExecutePlan() /home/postgres/develop/.../src/backend/executor/execMain.c:1696
10 standard_ExecutorRun() /home/postgres/develop/.../src/backend/executor/execMain.c:309
9 PortalRunSelect() /home/postgres/develop/.../src/backend/tcop/pquery.c:953
8 PortalRun() /home/postgres/develop/.../src/backend/tcop/pquery.c:807
7 exec_simple_query() /home/postgres/develop/.../src/backend/tcop/postgres.c:992
6 PostgresMain() /home/postgres/develop/.../src/backend/tcop/postgres.c:3617
5 BackendRun() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:3449
4 BackendStartup() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:3063
3 ServerLoop() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:1387
2 PostmasterMain() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:1040
1 main() /home/postgres/develop/.../src/backend/main/main.c:188
这里的ExecutePlan()函数就比较简单了,主要就是从硬盘上取出每一个tuple来,放入到des中去。由于执行流程实在简单,只是修改我们原有的数据结构的一些参数,例如当时访问了多少条tuple了等等,所以这里不再绘图。
8.PortalDrop(portal, false);
9.CommandCounterIncrement();
这里就非常简单了。
最后说明一下,当执行完exec_simple_query() 之后,postgresql重新进入循环,再次执行到PostgresMain函数的第3565行的ReadyForQuery(whereToSendOutput);时,才通过库函数进行网络传送给客户端查询的结果数据。
为完整起见,我把全部需要的数据结构绘一张图,上传到这里,供参考。
http://blog.sciencenet.cn/home.php?mod=space&uid=419883&do=blog&id=318721
假定我们数据库中已经有如下表,并填充了数据:
CREATE TABLE pois
(
uid integer not null,
catcode VARCHAR(32) not null,
);
现在我们用psql发送请求:select catcode from pois;
程序已经执行完了stmt = (Node *) pg_plan_query(query, cursorOptions, boundParams);了。
我们来看看接下来需要执行的函数调用:
- portal = CreatePortal("", true, true);
- PortalDefineQuery(portal,
NULL,
query_string,
commandTag,
plantree_list,
NULL); - PortalStart(portal, NULL, InvalidSnapshot);
- PortalSetResultFormat(portal, 1, &format);
- receiver = CreateDestReceiver(dest);
- SetRemoteDestReceiverParams(receiver, portal);
- (void) PortalRun(portal,
FETCH_ALL,
isTopLevel,
receiver,
receiver,
completionTag); - PortalDrop(portal, false);
- CommandCounterIncrement();
我们先来看/backend/executor/exeMain.c中的注释,然后分别对上面的调用分析。
The old ExecutorMain() has been replaced by ExecutorStart(),ExecutorRun() and ExecutorEnd()
These three procedures are the external interfaces to the executor.In each case, the query descriptor is required as an argument.
ExecutorStart() must be called at the beginning of execution of any query plan and ExecutorEnd() should always be called at the end of execution of a plan.
看样子ExecutorStart(),ExecutorRun() and ExecutorEnd()贯穿整个executor的全过程。
1.portal = CreatePortal("", true, true);
是创建一个名字为“”的portal,创建之后如下图,并插入到PortalHashTable的hash表中:
2.PortalDefineQuery(portal,
NULL,
query_string,
commandTag,
plantree_list,
NULL);
该函数只是对上面的portal进行进一步的初始化,比较重要的一个赋值是:portal->stmts=plantree_list.
赋值完之后如下图:
3.PortalStart(portal, NULL, InvalidSnapshot);
其中最主要的调用是 InitPlan() ,调用堆栈是:
postgresql Thread [C/C++ Attach to Application]
gdb Debugger (5/1/10 10:16 AM) (Suspended)
Thread [1] (Suspended)
10 InitPlan() /home/postgres/develop/.../src/backend/executor/execMain.c:649
9 standard_ExecutorStart() /home/postgres/develop/.../src/backend/executor/execMain.c:219
8 PortalStart() /home/postgres/develop/.../src/backend/tcop/pquery.c:539
7 exec_simple_query() /home/postgres/develop/.../src/backend/tcop/postgres.c:953
6 PostgresMain() /home/postgres/develop/.../src/backend/tcop/postgres.c:3617
5 BackendRun() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:3449
4 BackendStartup() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:3063
3 ServerLoop() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:1387
2 PostmasterMain() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:1040
1 main() /home/postgres/develop/.../src/backend/main/main.c:188 0x081e7ee7
到此为止,我们形成的数据结构有些庞大了,如下图(有谁能告诉我哪儿能上传大图的?picasa不行,flickr不行):
更清晰的全图可以从这里下载。
但是有几个重要的可以罗列一下,可以号称3大天王:
- QueryDesc
- SeqScanState
- EState
4.PortalSetResultFormat(portal, 1, &format);
该函数的主要作用是格式化输出字段。共有natt=1,格式化赋为0,0默认为输出为text。如源码中的注释:
format = 0; /* TEXT is default */
5.receiver = CreateDestReceiver(dest);
6.SetRemoteDestReceiverParams(receiver, portal);
其中dest=DestRemote
这一个阶段比较简单,最终形成的数据结构为(图中做了简化,但不影响理解):
7.(void) PortalRun(portal,
FETCH_ALL,
isTopLevel,
receiver,
receiver,
completionTag);
千辛万苦终于到了portalrun了。
顺序抽取tuple的主循环是ExecutePlan() ,调用堆栈为:
gdb Debugger (5/2/10 5:14 PM) (Suspended)
Thread [1] (Suspended)
11 ExecutePlan() /home/postgres/develop/.../src/backend/executor/execMain.c:1696
10 standard_ExecutorRun() /home/postgres/develop/.../src/backend/executor/execMain.c:309
9 PortalRunSelect() /home/postgres/develop/.../src/backend/tcop/pquery.c:953
8 PortalRun() /home/postgres/develop/.../src/backend/tcop/pquery.c:807
7 exec_simple_query() /home/postgres/develop/.../src/backend/tcop/postgres.c:992
6 PostgresMain() /home/postgres/develop/.../src/backend/tcop/postgres.c:3617
5 BackendRun() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:3449
4 BackendStartup() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:3063
3 ServerLoop() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:1387
2 PostmasterMain() /home/postgres/develop/.../src/backend/postmaster/postmaster.c:1040
1 main() /home/postgres/develop/.../src/backend/main/main.c:188
这里的ExecutePlan()函数就比较简单了,主要就是从硬盘上取出每一个tuple来,放入到des中去。由于执行流程实在简单,只是修改我们原有的数据结构的一些参数,例如当时访问了多少条tuple了等等,所以这里不再绘图。
8.PortalDrop(portal, false);
9.CommandCounterIncrement();
这里就非常简单了。
最后说明一下,当执行完exec_simple_query() 之后,postgresql重新进入循环,再次执行到PostgresMain函数的第3565行的ReadyForQuery(whereToSendOutput);时,才通过库函数进行网络传送给客户端查询的结果数据。
为完整起见,我把全部需要的数据结构绘一张图,上传到这里,供参考。
http://blog.sciencenet.cn/home.php?mod=space&uid=419883&do=blog&id=318721
- Postgresql Executor 阶段内存结构
- postgresql中plantree内存结构
- postgresql中query tree内存结构
- PostgreSQL学习第十一篇 进程及内存结构
- postgresql进程结构
- PostgreSQL源码结构
- PostgreSQL源码结构
- PostgreSQL源码结构
- PostgreSQL源码结构
- postgresql导出表结构
- Postgresql逻辑结构整理
- PostgreSQL FunctionCallInfoData结构体
- Executor
- Executor
- Executor
- Executor
- Executor
- Executor
- 终于完成的webbrowser永久记录cookie功能
- 百万数据查询优化技巧三十则
- Struts中,bean write的属性
- Dos批处理读取配置文件的方法
- 一个苏州IT人的5年挨踢经历-------面试篇(之二)
- Postgresql Executor 阶段内存结构
- Postmaster的Memory Context 初始化内存结构
- Postmaster的Shared Memory中的shared buffer pool内存结构
- Postmaster的Shared Memory中的shmem index table 内存结构
- 驱动编程---来个例子感性认识下
- C++ 友元函数
- [转载]PostgreSQL可以弥补MySQL数据库的哪些缺点
- 正则表达式
- C++ 友元函数 类和实例