万达换票券 发表于 2016-11-21 08:03:27

PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询四:分析重写成querytree

话说查询“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,comp from test1,test2 wheretest1.id=test2.id;
  
上面的图《例子里查询语句对应的querytree结构图》就是SQL语句“select cname,comp from test1,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.iyunv.com
页: [1]
查看完整版本: PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询四:分析重写成querytree