PostgreSQL的set_base_rel_sizes函数分析
这篇文章主要讲解了“PostgreSQL的set_base_rel_sizes函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL的set_base_rel_sizes函数分析”吧!
在set_base_rel_sizes函数调用过程中,如RTE为子查询,则生成子查询的访问路径,通过调用函数set_subquery_pathlist实现。
make_one_rel源代码:
RelOptInfo*make_one_rel(PlannerInfo*root,List*joinlist){//.../**Computesizeestimatesandconsider_parallelflagsforeachbaserel,*thengenerateaccesspaths.*/set_base_rel_sizes(root);//估算Relation的Size并且设置consider_parallel标记//...}一、数据结构
RelOptInfo
如前所述,RelOptInfo数据结构贯穿整个优化过程.
typedefstructRelOptInfo{NodeTagtype;//节点标识RelOptKindreloptkind;//RelOpt类型/*allrelationsincludedinthisRelOptInfo*/Relidsrelids;/*Relids(rtindex)集合setofbaserelids(rangetableindexes)*//*sizeestimatesgeneratedbyplanner*/doublerows;/*结果元组的估算数量estimatednumberofresulttuples*//*per-relationplannercontrolflags*/boolconsider_startup;/*是否考虑启动成本?是,需要保留启动成本低的路径keepcheap-startup-costpaths?*/boolconsider_param_startup;/*是否考虑参数化?的路径ditto,forparameterizedpaths?*/boolconsider_parallel;/*是否考虑并行处理路径considerparallelpaths?*//*defaultresulttargetlistforPathsscanningthisrelation*/structPathTarget*reltarget;/*扫描该Relation时默认的结果listofVars/Exprs,cost,width*//*materializationinformation*/List*pathlist;/*访问路径链表Pathstructures*/List*ppilist;/*路径链表中使用参数化路径进行ParamPathInfosusedinpathlist*/List*partial_pathlist;/*partialPaths*/structPath*cheapest_startup_path;//代价最低的启动路径structPath*cheapest_total_path;//代价最低的整体路径structPath*cheapest_unique_path;//代价最低的获取唯一值的路径List*cheapest_parameterized_paths;//代价最低的参数化路径链表/*parameterizationinformationneededforbothbaserelsandjoinrels*//*(seealsolateral_varsandlateral_referencers)*/Relidsdirect_lateral_relids;/*使用lateral语法,需依赖的Relidsrelsdirectlylaterallyreferenced*/Relidslateral_relids;/*minimumparameterizationofrel*//*informationaboutabaserel(notsetforjoinrels!)*///reloptkind=RELOPT_BASEREL时使用的数据结构Indexrelid;/*RelationID*/Oidreltablespace;/*表空间containingtablespace*/RTEKindrtekind;/*基表?子查询?还是函数等等?RELATION,SUBQUERY,FUNCTION,etc*/AttrNumbermin_attr;/*最小的属性编号smallestattrnoofrel(often<0)*/AttrNumbermax_attr;/*最大的属性编号largestattrnoofrel*/Relids*attr_needed;/*数组arrayindexed[min_attr..max_attr]*/int32*attr_widths;/*属性宽度arrayindexed[min_attr..max_attr]*/List*lateral_vars;/*关系依赖的Vars/PHVsLATERALVarsandPHVsreferencedbyrel*/Relidslateral_referencers;/*依赖该关系的Relidsrelsthatreferencemelaterally*/List*indexlist;/*该关系的IndexOptInfo链表listofIndexOptInfo*/List*statlist;/*统计信息链表listofStatisticExtInfo*/BlockNumberpages;/*块数sizeestimatesderivedfrompg_class*/doubletuples;/*元组数*/doubleallvisfrac;/*?*/PlannerInfo*subroot;/*如为子查询,存储子查询的rootifsubquery*/List*subplan_params;/*如为子查询,存储子查询的参数ifsubquery*/intrel_parallel_workers;/*并行执行,需要多少个workers?wantednumberofparallelworkers*//*Informationaboutforeigntablesandforeignjoins*///FDW相关信息Oidserverid;/*identifiesserverforthetableorjoin*/Oiduserid;/*identifiesusertocheckaccessas*/booluseridiscurrent;/*joinisonlyvalidforcurrentuser*//*use"structFdwRoutine"toavoidincludingfdwapi.hhere*/structFdwRoutine*fdwroutine;void*fdw_private;/*cachespaceforrememberingifwehaveproventhisrelationunique*///已知的,可保证唯一元组返回的Relids链表List*unique_for_rels;/*knownuniquefortheseotherrelid*set(s)*/List*non_unique_for_rels;/*已知的,返回的数据不唯一的Relids链表knownnotuniquefortheseset(s)*//*usedbyvariousscansandjoins:*/List*baserestrictinfo;/*如为基本关系,则存储约束条件RestrictInfostructures(ifbaserel)*/QualCostbaserestrictcost;/*解析约束表达式的成本?costofevaluatingtheabove*/Indexbaserestrict_min_security;/*最低安全等级minsecurity_levelfoundin*baserestrictinfo*/List*joininfo;/*连接语句的约束条件信息RestrictInfostructuresforjoinclauses*involvingthisrel*/boolhas_eclass_joins;/*是否存在等价类连接?True意味着joininfo并不完整,,Tmeansjoininfoisincomplete*//*usedbypartitionwisejoins:*///是否尝试partitionwise连接,这是PG11的一个新特性.boolconsider_partitionwise_join;/*considerpartitionwise*joinpaths?(if*partitionedrel)*/Relidstop_parent_relids;/*Relidsoftopmostparents(if"other"*rel)*//*usedforpartitionedrelations*///分区表使用PartitionSchemepart_scheme;/*分区的schemaPartitioningscheme.*/intnparts;/*分区数numberofpartitions*/structPartitionBoundInfoData*boundinfo;/*分区边界信息Partitionbounds*/List*partition_qual;/*分区约束partitionconstraint*/structRelOptInfo**part_rels;/*分区的RelOptInfo数组ArrayofRelOptInfosofpartitions,*storedinthesameorderofbounds*/List**partexprs;/*非空分区键表达式Non-nullablepartitionkeyexpressions.*/List**nullable_partexprs;/*可为空的分区键表达式Nullablepartitionkeyexpressions.*/List*partitioned_child_rels;/*RTIndexes链表ListofRTindexes.*/}RelOptInfo;二、源码解读
set_rel_size
如前所述,set_rel_size函数估算关系的大小,如RTE为子查询,则调用set_subquery_pathlist方法生成子查询访问路径,相关代码如下:
/**set_rel_size*Setsizeestimatesforabaserelation*/staticvoidset_rel_size(PlannerInfo*root,RelOptInfo*rel,Indexrti,RangeTblEntry*rte){if(rel->reloptkind==RELOPT_BASEREL&&relation_excluded_by_constraints(root,rel,rte)){//...}else{switch(rel->rtekind){case//...//...caseRTE_SUBQUERY://子查询/**Subqueriesdon'tsupportmakingachoicebetween*parameterizedandunparameterizedpaths,sojustgoahead*andbuildtheirpathsimmediately.*/set_subquery_pathlist(root,rel,rti,rte);//生成子查询访问路径break;case...}//...}//...}
set_subquery_pathlist
生成子查询的扫描路径,在生成过程中尝试下推外层的限制条件(减少参与运算的元组数量),并调用subquery_planner生成执行计划.
/**set_subquery_pathlist*GenerateSubqueryScanaccesspathsforasubqueryRTE*生成子查询的扫描路径**Wedon'tcurrentlysupportgeneratingparameterizedpathsforsubqueries*bypushingjoinclausesdownintothem;itseemstooexpensivetore-plan*thesubquerymultipletimestoconsiderdifferentalternatives.*(XXXthatcouldstandtobereconsidered,nowthatweusePaths.)*Sothepathsmadeherewillbeparameterizedifthesubquerycontains*LATERALreferences,otherwisenot.Aslongasthat'strue,there'snoneed*foraseparateset_subquery_sizephase:justmakethepathsrightaway.*/staticvoidset_subquery_pathlist(PlannerInfo*root,RelOptInfo*rel,Indexrti,RangeTblEntry*rte){Query*parse=root->parse;Query*subquery=rte->subquery;Relidsrequired_outer;pushdown_safety_infosafetyInfo;doubletuple_fraction;RelOptInfo*sub_final_rel;ListCell*lc;/**MustcopytheQuerysothatplanningdoesn'tmessuptheRTEcontents*(reallyreallyneedtofixtheplannertonotscribbleonitsinput,*someday...butseeremove_unused_subquery_outputstostartwith).*/subquery=copyObject(subquery);//拷贝/**Ifit'saLATERALsubquery,itmightcontainsomeVarsofthecurrent*querylevel,requiringittobetreatedasparameterized,eventhough*wedon'tsupportpushingdownjoinqualsintosubqueries.*/required_outer=rel->lateral_relids;//外层的Relids/**Zerooutresultareaforsubquery_is_pushdown_safe,sothatitcanset*flagsasneededwhilerecursing.Inparticular,weneedaworkspace*forkeepingtrackofunsafe-to-referencecolumns.unsafeColumns[i]*willbesettrueifwefindthatoutputcolumniofthesubqueryis*unsafetouseinapushed-downqual.*/memset(&safetyInfo,0,sizeof(safetyInfo));safetyInfo.unsafeColumns=(bool*)palloc0((list_length(subquery->targetList)+1)*sizeof(bool));/**Ifthesubqueryhasthe"security_barrier"flag,itmeansthesubquery*originatedfromaviewthatmustenforcerowlevelsecurity.Thenwe*mustnotpushdownqualsthatcontainleakyfunctions.(Ideallythis*wouldbecheckedinsidesubquery_is_pushdown_safe,butsincewedon't*currentlypasstheRTEtothatfunction,wemustdoithere.)*/safetyInfo.unsafeLeaky=rte->security_barrier;/**Ifthereareanyrestrictionclausesthathavebeenattachedtothe*subqueryrelation,considerpushingthemdowntobecomeWHEREorHAVING*qualsofthesubqueryitself.Thistransformationisusefulbecauseit*mayallowustogenerateabetterplanforthesubquerythanevaluating*allthesubqueryoutputrowsandthenfilteringthem.*限制条件是否可以下推到子查询中?如可以,优化器有可能生成更好的执行计划**Thereareseveralcaseswherewecannotpushdownclauses.Restrictions*involvingthesubqueryarecheckedbysubquery_is_pushdown_safe().*Restrictionsonindividualclausesarecheckedby*qual_is_pushdown_safe().Also,wedon'twanttopushdown*pseudoconstantclauses;bettertohavethegatingnodeabovethe*subquery.**Non-pushed-downclauseswillgetevaluatedasqpqualsofthe*SubqueryScannode.**XXXArethereanycaseswherewewanttomakeapolicydecisionnotto*pushdownapushablequal,becauseit'dresultinaworseplan?*/if(rel->baserestrictinfo!=NIL&&subquery_is_pushdown_safe(subquery,subquery,&safetyInfo)){//可以下推限制条件/*OKtoconsiderpushingdownindividualquals*/List*upperrestrictlist=NIL;ListCell*l;foreach(l,rel->baserestrictinfo)//遍历子查询上的限制条件{RestrictInfo*rinfo=(RestrictInfo*)lfirst(l);Node*clause=(Node*)rinfo->clause;if(!rinfo->pseudoconstant&&qual_is_pushdown_safe(subquery,rti,clause,&safetyInfo)){/*Pushitdown*/subquery_push_qual(subquery,rte,rti,clause);//下推限制条件}else{/*Keepitintheupperquery*/upperrestrictlist=lappend(upperrestrictlist,rinfo);//保留在上层中}}rel->baserestrictinfo=upperrestrictlist;/*Wedon'tbotherrecomputingbaserestrict_min_security*/}pfree(safetyInfo.unsafeColumns);/**Theupperquerymightnotuseallthesubquery'soutputcolumns;if*not,wecansimplify.*/remove_unused_subquery_outputs(subquery,rel);/**Wecansafelypasstheoutertuple_fractiondowntothesubqueryifthe*outerlevelhasnojoining,aggregation,orsortingtodo.Otherwise*we'dbettertellthesubquerytoplanforfullretrieval.(XXXThis*couldprobablybemademoreintelligent...)*/if(parse->hasAggs||parse->groupClause||parse->groupingSets||parse->havingQual||parse->distinctClause||parse->sortClause||has_multiple_baserels(root))tuple_fraction=0.0;/*defaultcase*/elsetuple_fraction=root->tuple_fraction;/*plan_paramsshouldnotbeinuseincurrentquerylevel*/Assert(root->plan_params==NIL);/*GenerateasubrootandPathsforthesubquery*/rel->subroot=subquery_planner(root->glob,subquery,root,false,tuple_fraction);//调用subquery_planner获取子查询的执行计划/*Isolatetheparamsneededbythisspecificsubplan*/rel->subplan_params=root->plan_params;root->plan_params=NIL;/**It'spossiblethatconstraintexclusionprovedthesubqueryempty.If*so,it'sdesirabletoproduceanunadorneddummypathsothatwewill*recognizeappropriateoptimizationsatthisquerylevel.*/sub_final_rel=fetch_upper_rel(rel->subroot,UPPERREL_FINAL,NULL);//子查询返回的最终关系if(IS_DUMMY_REL(sub_final_rel)){set_dummy_rel_pathlist(rel);return;}/**Markrelwithestimatedoutputrows,width,etc.Notethatwehaveto*dothisbeforegeneratingouter-querypaths,elsecost_subqueryscanis*nothappy.*/set_subquery_size_estimates(root,rel);//设置子查询的估算信息/**ForeachPaththatsubquery_plannerproduced,makeaSubqueryScanPath*intheouterquery.*/foreach(lc,sub_final_rel->pathlist)//遍历最终关系的访问路径{Path*subpath=(Path*)lfirst(lc);List*pathkeys;/*Convertsubpath'spathkeystoouterrepresentation*///转换pathkeys为外层的表示法pathkeys=convert_subquery_pathkeys(root,rel,subpath->pathkeys,make_tlist_from_pathtarget(subpath->pathtarget));/*Generateouterpathusingthissubpath*/add_path(rel,(Path*)create_subqueryscan_path(root,rel,subpath,pathkeys,required_outer));//通过子查询路径生成外层访问路径}/*Ifouterrelallowsparallelism,dosameforpartialpaths.*/if(rel->consider_parallel&&bms_is_empty(required_outer))//是否可以并行处理{/*Ifconsider_parallelisfalse,thereshouldbenopartialpaths.*/Assert(sub_final_rel->consider_parallel||sub_final_rel->partial_pathlist==NIL);/*Sameforpartialpaths.*/foreach(lc,sub_final_rel->partial_pathlist){Path*subpath=(Path*)lfirst(lc);List*pathkeys;/*Convertsubpath'spathkeystoouterrepresentation*/pathkeys=convert_subquery_pathkeys(root,rel,subpath->pathkeys,make_tlist_from_pathtarget(subpath->pathtarget));/*Generateouterpathusingthissubpath*/add_partial_path(rel,(Path*)create_subqueryscan_path(root,rel,subpath,pathkeys,required_outer));}}}//--------------------------------------------------------create_subqueryscan_path/**create_subqueryscan_path*Createsapathcorrespondingtoascanofasubquery,*returningthepathnode.*/SubqueryScanPath*create_subqueryscan_path(PlannerInfo*root,RelOptInfo*rel,Path*subpath,List*pathkeys,Relidsrequired_outer){SubqueryScanPath*pathnode=makeNode(SubqueryScanPath);pathnode->path.pathtype=T_SubqueryScan;//路径类型:子查询扫描pathnode->path.parent=rel;//父RelOptInfopathnode->path.pathtarget=rel->reltarget;//投影列pathnode->path.param_info=get_baserel_parampathinfo(root,rel,required_outer);//参数化信息pathnode->path.parallel_aware=false;//并行相关参数pathnode->path.parallel_safe=rel->consider_parallel&&subpath->parallel_safe;pathnode->path.parallel_workers=subpath->parallel_workers;pathnode->path.pathkeys=pathkeys;//排序键pathnode->subpath=subpath;//子访问路径cost_subqueryscan(pathnode,root,rel,pathnode->path.param_info);//子查询的成本returnpathnode;}//--------------------------------------------------------cost_subqueryscan/**cost_subqueryscan*DeterminesandreturnsthecostofscanningasubqueryRTE.**'baserel'istherelationtobescanned*'param_info'istheParamPathInfoifthisisaparameterizedpath,elseNULL*/voidcost_subqueryscan(SubqueryScanPath*path,PlannerInfo*root,RelOptInfo*baserel,ParamPathInfo*param_info){Coststartup_cost;Costrun_cost;QualCostqpqual_cost;Costcpu_per_tuple;/*Shouldonlybeappliedtobaserelationsthataresubqueries*/Assert(baserel->relid>0);Assert(baserel->rtekind==RTE_SUBQUERY);/*Markthepathwiththecorrectrowestimate*/if(param_info)path->path.rows=param_info->ppi_rows;elsepath->path.rows=baserel->rows;/**Costofpathiscostofevaluatingthesubplan,pluscostofevaluating*anyrestrictionclausesandtlistthatwillbeattachedtothe*SubqueryScannode,pluscpu_tuple_costtoaccountforselectionand*projectionoverhead.*/path->path.startup_cost=path->subpath->startup_cost;path->path.total_cost=path->subpath->total_cost;get_restriction_qual_cost(root,baserel,param_info,&qpqual_cost);startup_cost=qpqual_cost.startup;cpu_per_tuple=cpu_tuple_cost+qpqual_cost.per_tuple;run_cost=cpu_per_tuple*baserel->tuples;/*tlistevalcostsarepaidperoutputrow,notpertuplescanned*/startup_cost+=path->path.pathtarget->cost.startup;run_cost+=path->path.pathtarget->cost.per_tuple*path->path.rows;path->path.startup_cost+=startup_cost;path->path.total_cost+=startup_cost+run_cost;}三、跟踪分析
测试脚本如下:
selectt1.*,t2.dwbh,t2.counterfromt_dwxxt1,(selectdwbh,count(*)ascounterfromt_grxxgroupbydwbh)t2wheret1.dwbh=t2.dwbhandt1.dwbh='1001';
启动gdb:
(gdb)cContinuing.Breakpoint1,set_subquery_pathlist(root=0x2d749b0,rel=0x2d34dd0,rti=2,rte=0x2d341a0)atallpaths.c:20822082Query*parse=root->parse;
进入函数set_subquery_pathlist,输入参数中的root->simple_rel_array[2],rtekind为RTE_SUBQUERY子查询
(gdb)p*root->simple_rel_array[2]$13={type=T_RelOptInfo,reloptkind=RELOPT_BASEREL,relids=0x2d6a428,rows=0,consider_startup=false,consider_param_startup=false,consider_parallel=true,reltarget=0x2d6a440,pathlist=0x0,ppilist=0x0,partial_pathlist=0x0,cheapest_startup_path=0x0,cheapest_total_path=0x0,cheapest_unique_path=0x0,cheapest_parameterized_paths=0x0,direct_lateral_relids=0x0,lateral_relids=0x0,relid=2,reltablespace=0,rtekind=RTE_SUBQUERY,min_attr=0,max_attr=2,attr_needed=0x2d69b00,attr_widths=0x2d69b50,lateral_vars=0x0,lateral_referencers=0x0,indexlist=0x0,statlist=0x0,pages=0,tuples=0,allvisfrac=0,subroot=0x0,subplan_params=0x0,rel_parallel_workers=-1,serverid=0,userid=0,useridiscurrent=false,fdwroutine=0x0,fdw_private=0x0,unique_for_rels=0x0,non_unique_for_rels=0x0,baserestrictinfo=0x2d6b648,baserestrictcost={startup=0,per_tuple=0},baserestrict_min_security=0,joininfo=0x0,has_eclass_joins=true,top_parent_relids=0x0,part_scheme=0x0,nparts=0,boundinfo=0x0,partition_qual=0x0,part_rels=0x0,partexprs=0x0,nullable_partexprs=0x0,partitioned_child_rels=0x0}(gdb)p*rte$10={type=T_RangeTblEntry,rtekind=RTE_SUBQUERY,relid=0,relkind=0'\000',tablesample=0x0,subquery=0x2d342b0,security_barrier=false,jointype=JOIN_INNER,joinaliasvars=0x0,functions=0x0,funcordinality=false,tablefunc=0x0,values_lists=0x0,ctename=0x0,ctelevelsup=0,self_reference=false,coltypes=0x0,coltypmods=0x0,colcollations=0x0,enrname=0x0,enrtuples=0,alias=0x2c82728,eref=0x2d35328,lateral=false,inh=false,inFromCl=true,requiredPerms=0,checkAsUser=0,selectedCols=0x0,insertedCols=0x0,updatedCols=0x0,securityQuals=0x0}
下推限制条件:
...(gdb)n2157qual_is_pushdown_safe(subquery,rti,clause,&safetyInfo))(gdb)2156if(!rinfo->pseudoconstant&&(gdb)2160subquery_push_qual(subquery,rte,rti,clause);
tuple_fraction设置为0.0
...(gdb)2193tuple_fraction=0.0;/*defaultcase*/
调用subquery_planner获取执行计划:
(gdb)n2201rel->subroot=subquery_planner(root->glob,subquery,
获取子查询生成的最终关系,reloptkind为RELOPT_UPPER_REL
...(gdb)2214sub_final_rel=fetch_upper_rel(rel->subroot,UPPERREL_FINAL,NULL);(gdb)2216if(IS_DUMMY_REL(sub_final_rel))(gdb)p*sub_final_rel$16={type=T_RelOptInfo,reloptkind=RELOPT_UPPER_REL,relids=0x0,rows=0,consider_startup=false,consider_param_startup=false,consider_parallel=true,reltarget=0x2d7bd50,pathlist=0x2d7be10,ppilist=0x0,partial_pathlist=0x0,cheapest_startup_path=0x2d7aaa8,cheapest_total_path=0x2d7aaa8,cheapest_unique_path=0x0,cheapest_parameterized_paths=0x2d7be60,direct_lateral_relids=0x0,lateral_relids=0x0,relid=0,reltablespace=0,rtekind=RTE_RELATION,min_attr=0,max_attr=0,attr_needed=0x0,attr_widths=0x0,lateral_vars=0x0,lateral_referencers=0x0,indexlist=0x0,statlist=0x0,pages=0,tuples=0,allvisfrac=0,subroot=0x0,subplan_params=0x0,rel_parallel_workers=0,serverid=0,userid=0,useridiscurrent=false,fdwroutine=0x0,fdw_private=0x0,unique_for_rels=0x0,non_unique_for_rels=0x0,baserestrictinfo=0x0,baserestrictcost={startup=0,per_tuple=0},baserestrict_min_security=0,joininfo=0x0,has_eclass_joins=false,top_parent_relids=0x0,part_scheme=0x0,nparts=0,boundinfo=0x0,partition_qual=0x0,part_rels=0x0,partexprs=0x0,nullable_partexprs=0x0,partitioned_child_rels=0x0}
成本最低的路径
(gdb)p*sub_final_rel->cheapest_total_path$17={type=T_AggPath,pathtype=T_Agg,parent=0x2d7b6d0,pathtarget=0x2d7adc8,param_info=0x0,parallel_aware=false,parallel_safe=true,parallel_workers=0,rows=10,startup_cost=0.29249999999999998,total_cost=20.143376803383145,pathkeys=0x0}
通过子查询访问路径生成外层的访问路径
(gdb)n2227set_subquery_size_estimates(root,rel);(gdb)2233foreach(lc,sub_final_rel->pathlist)(gdb)2235Path*subpath=(Path*)lfirst(lc);(gdb)2239pathkeys=convert_subquery_pathkeys(root,(gdb)2246create_subqueryscan_path(root,rel,subpath,(gdb)2245add_path(rel,(Path*)(gdb)2233foreach(lc,sub_final_rel->pathlist)
完成函数调用,结束处理
(gdb)set_rel_size(root=0x2d749b0,rel=0x2d34dd0,rti=2,rte=0x2d341a0)atallpaths.c:380380break;
执行计划如下:
testdb=#explainverboseselectt1.*,t2.dwbh,t2.counterfromt_dwxxt1,(selectdwbh,count(*)ascounterfromt_grxxgroupbydwbh)t2wheret1.dwbh=t2.dwbhandt1.dwbh='1001';QUERYPLAN--------------------------------------------------------------------------------------------------------NestedLoop(cost=0.58..28.65rows=10width=32)Output:t1.dwmc,t1.dwbh,t1.dwdz,t_grxx.dwbh,(count(*))->IndexScanusingt_dwxx_pkeyonpublic.t_dwxxt1(cost=0.29..8.30rows=1width=20)Output:t1.dwmc,t1.dwbh,t1.dwdzIndexCond:((t1.dwbh)::text='1001'::text)->GroupAggregate(cost=0.29..20.14rows=10width=12)Output:t_grxx.dwbh,count(*)GroupKey:t_grxx.dwbh->IndexOnlyScanusingidx_t_dwxx_grbhonpublic.t_grxx(cost=0.29..19.99rows=10width=4)Output:t_grxx.dwbhIndexCond:(t_grxx.dwbh='1001'::text)(11rows)
感谢各位的阅读,以上就是“PostgreSQL的set_base_rel_sizes函数分析”的内容了,经过本文的学习后,相信大家对PostgreSQL的set_base_rel_sizes函数分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。