PostgreSQL索引扫描成本估算中的函数分析
这篇文章主要介绍“PostgreSQL索引扫描成本估算中的函数分析”,在日常操作中,相信很多人在PostgreSQL索引扫描成本估算中的函数分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PostgreSQL索引扫描成本估算中的函数分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
一、数据结构IndexClauseSet
用于收集匹配索引的的条件语句
/*Datastructureforcollectingqualclausesthatmatchanindex*/typedefstruct{boolnonempty;/*Trueiflistsarenotallempty*//*ListsofRestrictInfos,oneperindexcolumn*/List*indexclauses[INDEX_MAX_KEYS];}IndexClauseSet;二、源码解读
get_index_paths
get_index_paths函数根据给定的索引和索引条件子句,构造索引访问路径(IndexPath).
//---------------------------------------------------get_index_paths/**get_index_paths*Givenanindexandasetofindexclausesforit,constructIndexPaths.*给定索引和索引条件子句,构造索引访问路径(IndexPaths).**Plainindexpathsaresentdirectlytoadd_path,whilepotential*bitmapindexpathsareaddedto*bitindexpathsforlaterprocessing.*Plain索引访问路径直接作为参数传入到函数add_path中,潜在可能的位图索引路径*被添加到bitindexpaths中供以后处理。**Thisisafairlysimplefrontendtobuild_index_paths().Itsreasonfor*existenceismainlytohandleScalarArrayOpExprqualsproperly.Ifthe*indexAMsupportsthemnatively,weshouldjustincludetheminsimple*indexpaths.Ifnot,weshouldexcludethemwhilebuildingsimpleindex*paths,andthenmakeaseparateattempttoincludetheminbitmappaths.*Furthermore,weshouldconsiderexcludinglower-orderScalarArrayOpExpr*qualssoastocreateorderedpaths.*该函数简单构造build_index_paths所需要的参数,并调用之.该函数存在的原因是正确*处理ScalarArrayOpExpr表达式.*/staticvoidget_index_paths(PlannerInfo*root,RelOptInfo*rel,IndexOptInfo*index,IndexClauseSet*clauses,List**bitindexpaths){List*indexpaths;boolskip_nonnative_saop=false;boolskip_lower_saop=false;ListCell*lc;/**Buildsimpleindexpathsusingtheclauses.AllowScalarArrayOpExpr*clausesonlyiftheindexAMsupportsthemnatively,andskipanysuch*clausesforindexcolumnsafterthefirst(sothatweproduceordered*pathsifpossible).*/indexpaths=build_index_paths(root,rel,index,clauses,index->predOK,ST_ANYSCAN,&skip_nonnative_saop,&skip_lower_saop);//调用build_index_paths函数/**Ifweskippedanylower-orderScalarArrayOpExprsonanindexwithanAM*thatsupportsthem,thentryagainincludingthoseclauses.Thiswill*producepathswithmoreselectivitybutnoordering.*/if(skip_lower_saop){indexpaths=list_concat(indexpaths,build_index_paths(root,rel,index,clauses,index->predOK,ST_ANYSCAN,&skip_nonnative_saop,NULL));}/**SubmitalltheonesthatcanformplainIndexScanplanstoadd_path.(A*plainIndexPathcanrepresenteitheraplainIndexScanoran*IndexOnlyScan,butforourpurposesherethatdistinctiondoesnot*matter.However,someoftheindexesmightsupportonlybitmapscans,*andthosewemustn'tsubmittoadd_pathhere.)*逐一把可以形成Plain索引扫描计划的的访问路径作为参数调用add_path*(plainIndexPath可以是常规的索引扫描或者是IndexOnlyScan)**Also,pickouttheonesthatareusableasbitmapscans.Forthat,we*mustdiscardindexesthatdon'tsupportbitmapscans,andwealsoare*onlyinterestedinpathsthathavesomeselectivity;weshoulddiscard*anythingthatwasgeneratedsolelyfororderingpurposes.*找出可用于位图扫描的索引*/foreach(lc,indexpaths)//遍历访问路径{IndexPath*ipath=(IndexPath*)lfirst(lc);if(index->amhasgettuple)add_path(rel,(Path*)ipath);//调用add_pathif(index->amhasgetbitmap&&(ipath->path.pathkeys==NIL||ipath->indexselectivity<1.0))*bitindexpaths=lappend(*bitindexpaths,ipath);//如可以,添加到位图索引扫描路径链表中}/**IftherewereScalarArrayOpExprclausesthattheindexcan'thandle*natively,generatebitmapscanpathsrelyingonexecutor-managed*ScalarArrayOpExpr.*/if(skip_nonnative_saop){indexpaths=build_index_paths(root,rel,index,clauses,false,ST_BITMAPSCAN,NULL,NULL);*bitindexpaths=list_concat(*bitindexpaths,indexpaths);}}//-----------------------------------------------------------build_index_paths/**build_index_paths*Givenanindexandasetofindexclausesforit,constructzero*ormoreIndexPaths.ItalsoconstructszeroormorepartialIndexPaths.*给定索引和该索引的条件,构造0-N个索引访问路径或partial索引访问路径(用于并行)**Wereturnalistofpathsbecause(1)thisroutinecheckssomecases*thatshouldcauseustonotgenerateanyIndexPath,and(2)insome*caseswewanttoconsiderbothaforwardandabackwardscan,soas*toobtainbothsortorders.Notethatthepathsarejustreturned*tothecallerandnotimmediatelyfedtoadd_path().*函数返回访问路径链表:(1)执行过程中的检查会导致产生不了索引访问路径*(2)在某些情况下,同时考虑正向/反向扫描,以便获得两种排序顺序。*注意:访问路径返回给调用方,不会马上反馈到函数add_path中**Attoplevel,useful_predicateshouldbeexactlytheindex'spredOKflag*(ie,trueifithasapredicatethatwasprovenfromtherestriction*clauses).WhenworkingonanarmofanORclause,useful_predicate*shouldbetrueifthepredicaterequiredthecurrentORlisttobeproven.*Notethatthisroutineshouldneverbecalledatalliftheindexhasan*unprovablepredicate.*在顶层,useful_predicate标记应与索引的predOK标记一致.在操作OR自己的arm(?)时,*如果谓词需要当前的OR链表证明,则useful_predicate应为T.*注意:如果索引有一个未经验证的谓词,则该例程不能被调用.**scantypeindicateswhetherwewanttocreateplainindexscans,bitmap*indexscans,orboth.Whenit'sST_BITMAPSCAN,wewillnotconsider*indexorderingwhiledecidingifaPathisworthgenerating.*scantype:提示是否创建plain/bitmap或者两者兼顾的索引扫描.*如该参数值为ST_BITMAPSCAN,则在决定访问路径是否产生时不会考虑使用索引排序**Ifskip_nonnative_saopisnon-NULL,weignoreScalarArrayOpExprclauses*unlesstheindexAMsupportsthemdirectly,andweset*skip_nonnative_saop*totrueifwefoundanysuchclauses(callermustinitializethevariable*tofalse).Ifit'sNULL,wedonotignoreScalarArrayOpExprclauses.*skip_nonnative_saop:*如为NOTNULL,除非索引的访问方法(AM)直接支持,否则会忽略*ScalarArrayOpExpr子句,如支持,则更新skip_nonnative_saop标记为T.*如为NULL,不能忽略ScalarArrayOpExpr子句.**Ifskip_lower_saopisnon-NULL,weignoreScalarArrayOpExprclausesfor*non-firstindexcolumns,andweset*skip_lower_saoptotrueifwefound*anysuchclauses(callermustinitializethevariabletofalse).Ifit's*NULL,wedonotignorenon-firstScalarArrayOpExprclauses,buttheywill*resultinconsideringthescan'soutputtobeunordered.*skip_lower_saop:*如为NOTNULL,ScalarArrayOpExpr子句中的首列不是索引列,则忽略之,*同时如果找到相应的子句,则设置skip_lower_saop标记为T.*如为NULL,除首个ScalarArrayOpExpr子句外,其他子句不能被忽略,但输出时不作排序**输入/输出参数:*'rel'istheindex'sheaprelation*rel-相应的RelOptInfo*'index'istheindexforwhichwewanttogeneratepaths*index-相应的索引IndexOptInfo*'clauses'isthecollectionofindexableclauses(RestrictInfonodes)*clauses-RestrictInfo节点集合*'useful_predicate'indicateswhethertheindexhasausefulpredicate*useful_predicate-提示索引是否有可用的谓词*'scantype'indicateswhetherweneedplainorbitmapscansupport*scantype-扫描类型,提示是否需要plain/bitmap扫描支持*'skip_nonnative_saop'indicateswhethertoacceptSAOPifindexAMdoesn't*skip_nonnative_saop-提示是否接受SAOP*'skip_lower_saop'indicateswhethertoacceptnon-first-columnSAOP*skip_lower_saop-提示是否接受非首列SAOP*/staticList*build_index_paths(PlannerInfo*root,RelOptInfo*rel,IndexOptInfo*index,IndexClauseSet*clauses,booluseful_predicate,ScanTypeControlscantype,bool*skip_nonnative_saop,bool*skip_lower_saop){List*result=NIL;IndexPath*ipath;List*index_clauses;List*clause_columns;Relidsouter_relids;doubleloop_count;List*orderbyclauses;List*orderbyclausecols;List*index_pathkeys;List*useful_pathkeys;boolfound_lower_saop_clause;boolpathkeys_possibly_useful;boolindex_is_ordered;boolindex_only_scan;intindexcol;/**Checkthatindexsupportsthedesiredscantype(s)*/switch(scantype){caseST_INDEXSCAN:if(!index->amhasgettuple)returnNIL;break;caseST_BITMAPSCAN:if(!index->amhasgetbitmap)returnNIL;break;caseST_ANYSCAN:/*eitherorbothareOK*/break;}/**1.Collecttheindexclausesintoasinglelist.*1.收集索引子句到单独的链表中**WebuildalistofRestrictInfonodesforclausestobeusedwiththis*index,alongwithanintegerlistoftheindexcolumnnumbers(zero*based)thateachclauseshouldbeusedwith.Theclausesareordered*byindexkey,sothatthecolumnnumbersformanondecreasingsequence.*(Thisorderisdependedonbybtreeandpossiblyotherplaces.)The*listscanbeempty,iftheindexAMallowsthat.*我们为将与此索引一起使用的子句构建了一个RestrictInfo节点链表,*以及每个子句应该与之一起使用的索引列编号(从0开始)的整数链表.*子句是按索引键排序的,因此列号形成一个非递减序列。*(这个排序取决于BTree和可能的其他地方).*如果索引访问方法(AM)允许,链表可为空.**found_lower_saop_clauseissettrueifweacceptaScalarArrayOpExpr*indexclauseforanon-firstindexcolumn.Thispreventsusfrom*assumingthatthescanresultisordered.(Actually,theresultis*stillorderedifthereareequalityconstraintsforallearlier*columns,butitseemstooexpensiveandnon-modularforthiscodetobe*awareofthatrefinement.)**WealsobuildaRelidssetshowingwhichouterrelsarerequiredbythe*selectedclauses.Anylateral_relidsareincludedinthat,butnot*otherwiseaccountedfor.*建立一个已选择的子句所依赖外部rels的Relids集合,包括lateral_relids.*/index_clauses=NIL;clause_columns=NIL;found_lower_saop_clause=false;outer_relids=bms_copy(rel->lateral_relids);for(indexcol=0;indexcol<index->ncolumns;indexcol++)//遍历索引列{ListCell*lc;foreach(lc,clauses->indexclauses[indexcol])//遍历该列所对应的约束条件{RestrictInfo*rinfo=(RestrictInfo*)lfirst(lc);//约束条件if(IsA(rinfo->clause,ScalarArrayOpExpr))//ScalarArrayOpExpr,TODO{if(!index->amsearcharray){if(skip_nonnative_saop){/*Ignorebecausenotsupportedbyindex*/*skip_nonnative_saop=true;continue;}/*Callerhadbetterintendthisonlyforbitmapscan*/Assert(scantype==ST_BITMAPSCAN);}if(indexcol>0){if(skip_lower_saop){/*Callerdoesn'twanttoloseindexordering*/*skip_lower_saop=true;continue;}found_lower_saop_clause=true;}}index_clauses=lappend(index_clauses,rinfo);//添加到链表中clause_columns=lappend_int(clause_columns,indexcol);outer_relids=bms_add_members(outer_relids,rinfo->clause_relids);}/**Ifnoclausesmatchthefirstindexcolumn,checkforamoptionalkey*restriction.Wecan'tgenerateascanoveranindexwith*amoptionalkey=falseunlessthere'satleastoneindexclause.*(Whenworkingoncolumnsafterthefirst,thistestcannotfail.It*isalwaysokayforcolumnsafterthefirsttonothaveany*clauses.)*/if(index_clauses==NIL&&!index->amoptionalkey)//没有约束条件,返回空指针returnNIL;}/*Wedonotwanttheindex'srelitselflistedinouter_relids*/outer_relids=bms_del_member(outer_relids,rel->relid);//去掉自身relid/*Enforceconventionthatouter_relidsisexactlyNULLifempty*/if(bms_is_empty(outer_relids))outer_relids=NULL;//设置为NULL/*Computeloop_countforcostestimationpurposes*///计算成本估算所需要的循环次数loop_countloop_count=get_loop_count(root,rel->relid,outer_relids);/**2.Computepathkeysdescribingindex'sordering,ifany,thenseehow*manyofthemareactuallyusefulforthisquery.Thisisnotrelevant*ifweareonlytryingtobuildbitmapindexscans,norifwehaveto*assumethescanisunordered.*2.计算描述索引排序的路径键(如果有的话),如存在的话,检查有多少对查询有用。*如果只是尝试构建位图索引扫描,或者扫描是无序的,那就无关紧要了。*/pathkeys_possibly_useful=(scantype!=ST_BITMAPSCAN&&!found_lower_saop_clause&&has_useful_pathkeys(root,rel));//是否存在可用的Pathkeysindex_is_ordered=(index->sortopfamily!=NULL);//索引是否排序?if(index_is_ordered&&pathkeys_possibly_useful)//索引排序&存在可用的Pathkeys{index_pathkeys=build_index_pathkeys(root,index,ForwardScanDirection);//创建正向(ForwardScanDirection)扫描排序键useful_pathkeys=truncate_useless_pathkeys(root,rel,index_pathkeys);//截断无用的Pathkeysorderbyclauses=NIL;orderbyclausecols=NIL;}elseif(index->amcanorderbyop&&pathkeys_possibly_useful)//访问方法可以通过操作符排序{/*seeifwecangenerateorderingoperatorsforquery_pathkeys*/match_pathkeys_to_index(index,root->query_pathkeys,&orderbyclauses,&orderbyclausecols);//是否可以生成排序操作符if(orderbyclauses)useful_pathkeys=root->query_pathkeys;//如可以,则赋值elseuseful_pathkeys=NIL;}else//设置为NULL{useful_pathkeys=NIL;orderbyclauses=NIL;orderbyclausecols=NIL;}/**3.Checkifanindex-onlyscanispossible.Ifwe'renotbuilding*plainindexscans,thisisn'trelevantsincebitmapscansdon'tsupport*indexdataretrievalanyway.*3.检查是否只需要扫描索引.如果我们不构建纯索引扫描,这是无关紧要的,*因为位图扫描不支持索引数据检索。*/index_only_scan=(scantype!=ST_BITMAPSCAN&&check_index_only(rel,index));/**4.Generateanindexscanpathiftherearerelevantrestrictionclauses*inthecurrentclauses,ORtheindexorderingispotentiallyusefulfor*latermergingorfinaloutputordering,ORtheindexhasauseful*predicate,ORanindex-onlyscanispossible.*4.如果当前子句中有相关的限制子句,或者索引排序对于以后的*合并或最终的输出排序可能有用,或者索引存在可用的谓词,*或者可能进行纯索引扫描,则生成索引扫描路径。*/if(index_clauses!=NIL||useful_pathkeys!=NIL||useful_predicate||index_only_scan){ipath=create_index_path(root,index,index_clauses,clause_columns,orderbyclauses,orderbyclausecols,useful_pathkeys,index_is_ordered?ForwardScanDirection:NoMovementScanDirection,index_only_scan,outer_relids,loop_count,false);//创建索引扫描路径result=lappend(result,ipath);//添加到结果链表中/**Ifappropriate,considerparallelindexscan.Wedon'tallow*parallelindexscanforbitmapindexscans.*如果合适,考虑并行索引扫描。如为位图索引,则不能使用并行.。*/if(index->amcanparallel&&rel->consider_parallel&&outer_relids==NULL&&scantype!=ST_BITMAPSCAN){ipath=create_index_path(root,index,index_clauses,clause_columns,orderbyclauses,orderbyclausecols,useful_pathkeys,index_is_ordered?ForwardScanDirection:NoMovementScanDirection,index_only_scan,outer_relids,loop_count,true);//创建并行索引扫描路径/**if,aftercostingthepath,wefindthatit'snotworthusing*parallelworkers,justfreeit.*/if(ipath->path.parallel_workers>0)//在worker>0的情况下add_partial_path(rel,(Path*)ipath);//添加partial路径elsepfree(ipath);}}/**5.Iftheindexisordered,abackwardsscanmightbeinteresting.*5.如果索引是已排序的(如BTree等),构建反向扫描(BackwardScanDirection)路径*/if(index_is_ordered&&pathkeys_possibly_useful){index_pathkeys=build_index_pathkeys(root,index,BackwardScanDirection);useful_pathkeys=truncate_useless_pathkeys(root,rel,index_pathkeys);if(useful_pathkeys!=NIL){ipath=create_index_path(root,index,index_clauses,clause_columns,NIL,NIL,useful_pathkeys,BackwardScanDirection,index_only_scan,outer_relids,loop_count,false);result=lappend(result,ipath);/*Ifappropriate,considerparallelindexscan*/if(index->amcanparallel&&rel->consider_parallel&&outer_relids==NULL&&scantype!=ST_BITMAPSCAN){ipath=create_index_path(root,index,index_clauses,clause_columns,NIL,NIL,useful_pathkeys,BackwardScanDirection,index_only_scan,outer_relids,loop_count,true);/**if,aftercostingthepath,wefindthatit'snotworth*usingparallelworkers,justfreeit.*/if(ipath->path.parallel_workers>0)add_partial_path(rel,(Path*)ipath);elsepfree(ipath);}}}returnresult;}三、跟踪分析
测试脚本如下
selecta.*,b.grbh,b.jefromt_dwxxa,lateral(selectt1.dwbh,t1.grbh,t2.jefromt_grxxt1innerjoint_jfxxt2ont1.dwbh=a.dwbhandt1.grbh=t2.grbh)bwherea.dwbh='1001'orderbyb.dwbh;
启动gdb
(gdb)bget_index_pathsBreakpoint1at0x74db5e:fileindxpath.c,line740.(gdb)cContinuing.Breakpoint1,get_index_paths(root=0x2704720,rel=0x27041b0,index=0x2713898,clauses=0x7fff834d8090,bitindexpaths=0x7fff834d81b0)atindxpath.c:740740boolskip_nonnative_saop=false;
选择t_dwxx的主键进行跟踪
(gdb)p*index$2={type=T_IndexOptInfo,indexoid=16738,reltablespace=0,rel=0x27041b0,pages=30,tuples=10000,tree_height=1,ncolumns=1,nkeycolumns=1,indexkeys=0x2713bd8,indexcollations=0x2713bf0,opfamily=0x2713c08,opcintype=0x2713c20,sortopfamily=0x2713c08,reverse_sort=0x2713c50,nulls_first=0x2713c68,canreturn=0x2713c38,relam=403,indexprs=0x0,indpred=0x0,indextlist=0x2713ba8,indrestrictinfo=0x2716c18,predOK=false,unique=true,immediate=true,hypothetical=false,amcanorderbyop=false,amoptionalkey=true,amsearcharray=true,amsearchnulls=true,amhasgettuple=true,amhasgetbitmap=true,amcanparallel=true,amcostestimate=0x94f0ad<btcostestimate>}--testdb=#selectrelnamefrompg_classwhereoid=16738;relname-------------t_dwxx_pkey(1row)--
进入函数build_index_paths
(gdb)stepbuild_index_paths(root=0x2704720,rel=0x27041b0,index=0x27135b8,clauses=0x7fff834d8090,useful_predicate=false,scantype=ST_ANYSCAN,skip_nonnative_saop=0x7fff834d7e27,skip_lower_saop=0x7fff834d7e26)atindxpath.c:864864List*result=NIL;
查看输入参数,其中clauses中的indexclauses数组,存储约束条件链表
(gdb)p*clauses$3={nonempty=true,indexclauses={0x2717728,0x0<repeats31times>}}(gdb)set$ri=(RestrictInfo*)clauses->indexclauses[0]->head->data.ptr_value
链表的第一个约束条件为:t_dwxx.dwbh(varno = 1, varattno = 2)='1001'(constvalue = 40986784)
(gdb)p*((OpExpr*)$ri->clause)->args$11={type=T_List,length=2,head=0x27169f8,tail=0x27169a8}(gdb)p*(Node*)((OpExpr*)$ri->clause)->args->head->data.ptr_value$12={type=T_RelabelType}(gdb)p*(Node*)((OpExpr*)$ri->clause)->args->head->next->data.ptr_value$13={type=T_Const}(gdb)set$tmp1=(RelabelType*)((OpExpr*)$ri->clause)->args->head->data.ptr_value(gdb)set$tmp2=(Const*)((OpExpr*)$ri->clause)->args->head->next->data.ptr_value(gdb)p*(Var*)$tmp1->arg$17={xpr={type=T_Var},varno=1,varattno=2,vartype=1043,vartypmod=24,varcollid=100,varlevelsup=0,varnoold=1,varoattno=2,location=147}(gdb)p*(Const*)$tmp2$18={xpr={type=T_Const},consttype=25,consttypmod=-1,constcollid=100,constlen=-1,constvalue=40986784,constisnull=false,constbyval=false,location=194}
扫描类型,ST_ANYSCAN,包括plain&bitmap
(gdb)n883switch(scantype)(gdb)pscantype$19=ST_ANYSCAN
Step 1:收集索引子句到单独的链表中
923for(indexcol=0;indexcol<index->ncolumns;indexcol++)(gdb)pouter_relids$20=(Relids)0x0(gdb)n927foreach(lc,clauses->indexclauses[indexcol])(gdb)pindexcol$21=0(gdb)n#rinfo约束条件:t_dwxx.dwbh='1001'929RestrictInfo*rinfo=(RestrictInfo*)lfirst(lc);(gdb)931if(IsA(rinfo->clause,ScalarArrayOpExpr))(gdb)
Step 1的主要逻辑:
(gdb)n955index_clauses=lappend(index_clauses,rinfo);(gdb)p*index_clausesCannotaccessmemoryataddress0x0(gdb)n956clause_columns=lappend_int(clause_columns,indexcol);(gdb)958rinfo->clause_relids);(gdb)957outer_relids=bms_add_members(outer_relids,
Step 1完成后:
(gdb)p*outer_relids$23={nwords=1,words=0x27177fc}(gdb)p*index_clauses$26={type=T_List,length=1,head=0x2717758,tail=0x2717758}(gdb)pouter_relids->words[0]$27=0-->无外部的Relids(gdb)p*clause_columns$31={type=T_IntList,length=1,head=0x27177a8,tail=0x27177a8}(gdb)pclause_columns->head->data.int_value$32=0-->列数组编号为0
循环次数:
(gdb)ploop_count$33=1
Step 2:计算描述索引排序的路径键(如果有的话),如存在的话,检查有多少对查询有用。
...(gdb)ppathkeys_possibly_useful$35=true(gdb)pindex_is_ordered$36=true
创建正向扫描排序键
(gdb)n994index_pathkeys=build_index_pathkeys(root,index,(gdb)p*index_pathkeysCannotaccessmemoryataddress0x0-->无需排序
Step 3:检查是否只需要扫描索引
(gdb)pindex_only_scan$37=false-->Noway!
Step 4:生成索引扫描路径
调用函数create_index_path(下节介绍)
1036ipath=create_index_path(root,index,(gdb)1049result=lappend(result,ipath);(gdb)p*ipath$38={path={type=T_IndexPath,pathtype=T_IndexScan,parent=0x27041b0,pathtarget=0x27134c8,param_info=0x0,parallel_aware=false,parallel_safe=true,parallel_workers=0,rows=1,startup_cost=0.28500000000000003,total_cost=8.3025000000000002,pathkeys=0x0},indexinfo=0x27135b8,indexclauses=0x2717778,indexquals=0x27178e8,indexqualcols=0x2717938,indexorderbys=0x0,indexorderbycols=0x0,indexscandir=ForwardScanDirection,indextotalcost=4.2925000000000004,indexselectivity=0.0001}
Step 5:构建反向扫描(BackwardScanDirection)路径
(gdb)pindex_is_ordered$41=true(gdb)ppathkeys_possibly_useful$42=true...(gdb)p*index_pathkeysCannotaccessmemoryataddress0x0-->无需排序
返回结果
1137returnresult;(gdb)1138}
到此,关于“PostgreSQL索引扫描成本估算中的函数分析”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。