话说查询“selectcname,comp from test1,test2 where test1.ID=test2.ID;” 发送到服务器端,走查询分支exec_simple_query,先调用start_xact_command初始化了事务管理相关对象和资源,接着调用pg_parse_query,通过Lex和Yacc对传入SQL语句进行词法语法解析,生成解析树。下来调用GetTransactionSnapshot方法做内存快照,然后调用pg_analyze_and_rewrite方法,进行语义分析把parsetree转换成querytree,然后对该querytree进行重写。
1
下面是对parseetree进行语义分析和查询重写的调用序列图。
Postgres服务进程简查之语义分析和查询重写调用序列图
上图红色方框中显示了对parsetree进行语义分析和查询重写的方法调用过程,在parse_analyze方法中对parsetree进行语义分析,生成querytree,在pg_rewrite_query方法中对前面生成的querytree进一步进行修改,最后把querytree返回给exec_simple_query。在parse_analyze方法中根据这个例子中语句生成的节点类型T_SelectStmt走transformSelectStmt分支,分别调用transformFromClause、transformTargetList、transformWhereClause方法处理from、目标属性、where子句。处理完后把目标传到pg_rewrite_query方法,在pg_rewrite_query方法里利用规则/rule对querytree中对应的目标进行重写,规则是查询重写处理的关键,pg的规则中pg_write系统表中。规则和触发器相似,都可以在某种条件下激活,可执行原命令之外的动作,区别是触发器多涉及到每个元组都执行一次,而规则对整个查询树querytree进行修改或额外的查询。一个语句如果涉及多个元组,规则一般比触发器效率高,但触发器更容易理解。
这部分内容涉及到结构和处理及代码量相当多,在这就不列举了,有兴趣的根据方法调用流程图看源码吧,下面给出处理完的结果querytree结构图。
例子里查询语句对应的querytree结构图
把这个例子再重复一下:
create table test1 (ID numeric(10),cnamevarchar(30));
create table test2 (ID numeric(10),compvarchar(30));
select cname,test2 wheretest1.ID=test2.ID;
上面的图《例子里查询语句对应的querytree结构图》就是sql语句“select cname,test2 where test1.ID=test2.ID”在pg里产生的querytree。
pg输出的querytree如下:
2011-11-23 06:57:39 HKT DETAIL: (
{query
:commandType 1
:querySource 0
:canSetTag true
:utilityStmt <>
:resultRelation 0
:intoClause <>
:hasAggs false
:hasWindowFuncs false
:hasSublinks false
:hasdistinctOn false
:hasRecursive false
:hasModifyingCTE false
:hasForUpdate false
:cteList <>
:rtable (
{RTE
:alias <>
:eref
{AliAS
:aliasname test1
:colnames ("ID""cname")
}
:rtekind 0
:relID 16394
:relkind r
:inh true
:inFromCl true
:requiredPerms 2
:checkAsUser 0
:selectedCols (b 9 10)
:modifIEdCols (b)
}
{RTE
:alias <>
:eref
{AliAS
:aliasname test2
:colnames ("ID""comp")
}
:rtekind 0
:relID 16397
:relkind r
:inh true
:inFromCl true
:requiredPerms 2
:checkAsUser 0
:selectedCols (b 9 10)
:modifIEdCols (b)
}
)
:jointree
{FROMEXPR
:fromList (
{RANGETBLREF
:rtindex 1
}
{RANGETBLREF
:rtindex 2
}
)
:quals
{OPEXPR
:opno 1752
:opfuncID 1718
:opresulttype 16
:opretset false
:opcollID 0
:inputcollID 0
:args (
{VAR
:varno 1
:varattno 1
:vartype 1700
:vartypmod 655364
:varcollID 0
:varlevelsup 0
:varnoold 1
:varoattno 1
:location 41
}
{VAR
:varno 2
:varattno 1
:vartype 1700
:vartypmod 655364
:varcollID 0
:varlevelsup 0
:varnoold 2
:varoattno 1
:location 50
}
)
:location 49
}
}
:targetList (
{TARGETENTRY
:expr
{VAR
:varno 1
:varattno 2
:vartype 1043
:vartypmod 34
:varcollID 100
:varlevelsup 0
:varnoold 1
:varoattno 2
:location 7
}
:resno 1
:resname cname
:ressortgroupref 0
:resorigtbl 16394
:resorigcol 2
:resjunk false
}
{TARGETENTRY
:expr
{VAR
:varno 2
:varattno 2
:vartype 1043
:vartypmod 34
:varcollID 100
:varlevelsup 0
:varnoold 2
:varoattno 2
:location 13
}
:resno 2
:resname comp
:ressortgroupref 0
:resorigtbl 16397
:resorigcol 2
:resjunk false
}
)
:returningList <>
:groupClause <>
:havingQual <>
:windowClause <>
:distinctClause <>
:sortClause <>
:limitOffset <>
:limitCount <>
:rowMarks <>
:setoperations <>
:constraintDeps <>
}
)
就到这儿吧。
------------ 转载请注明出处,来自博客: blog.csdn.net/beiigang beigang.iteye.com
总结以上是内存溢出为你收集整理的PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询四:分析重写成querytree全部内容,希望文章能够帮你解决PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询四:分析重写成querytree所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)