Plan ID Jumbling

From PostgreSQL wiki
Jump to navigationJump to search

This page describes the proposed feature for Postgres 18 or 19 that records a planid, similar to the existing queryid recorded by query jumbling (previously done by pg_stat_statements).

See Commitfest entry and pgsql-hackers thread.

What to jumble

The current thesis behind what should be jumbled (included in the planid hash) is that plans that have the same EXPLAIN (COSTS OFF) output should yield the same planid. That is, a difference in "plan shape" is what constitutes a different planid, but different costs/selectivity or execution time statistics do not.

Note that plan jumbling relies on the existing query jumbling logic and decisions for any expressions, and as such e.g. ignores A_Const nodes, so a plan with different parameter values but the same shape will yield the same planid.

Plan jumbling is currently proposed to occur during the existing treewalk in src/backend/optimizer/plan/setrefs.c, and as such fields that would cause us to descend down the plan tree must be ignored for jumbling instead, noted as "Indirect" in the table below.

Further, to ease maintenance we jumble any field that is not explicitly causing issues with a changing planid, even if the field is not actually used by src/backend/commands/explain.c for showing EXPLAIN (COSTS OFF).

We could alternatively omit any fields that are duplicated (e.g. only have one of IndexScan.indexqual and IndexScan.indexqualorig), or omit those only used by the executor (e.g. Plan.extParam) to optimize for jumbling performance at the expense of higher maintenance overhead (review to be done) when adding new fields.

Jumbling details for all plan struct (plannodes.h) fields

For easier review/discussion, the table below represents all fields under consideration to be jumbled/not jumbled:

Struct / Field Include in Jumble Hash? Why not? / Notes
Plan (abstract)
type Yes
disabled_nodes No Costing/selectivity information should be ignored
startup_cost No Costing/selectivity information should be ignored
total_cost No Costing/selectivity information should be ignored
plan_rows No Costing/selectivity information should be ignored
plan_width No Costing/selectivity information should be ignored
parallel_aware Yes
parallel_safe Yes
async_capable Yes
plan_node_id Yes
targetlist Yes
qual Yes
lefttree Indirect Jumbled via setrefs.c treewalk
righttree Indirect Jumbled via setrefs.c treewalk
initPlan Indirect Jumbled via planner.c subplans treewalk
extParam Yes
allParam Yes
Result
plan Yes
resconstantqual Yes
ProjectSet
plan Yes
ModifyTable
plan Yes
operation Yes
canSetTag Yes
nominalRelation Yes
rootRelation Yes
partColsUpdated Yes
resultRelations Yes
updateColnosLists Yes
withCheckOptionLists Yes
returningOldAlias Yes
returningNewAlias Yes
returningLists Yes
fdwPrivLists No Private data for the FDW
fdwDirectModifyPlans Yes
rowMarks Yes PlanRowMark nodes are ignored for jumbling
epqParam Yes
onConflictAction Yes
arbiterIndexes Yes
onConflictSet Yes
onConflictCols Yes
onConflictWhere Yes
exclRelRTI Yes
exclRelTlist Yes
mergeActionLists Yes
mergeJoinConditions Yes
Append
plan Yes
apprelids Yes
appendplans Indirect Jumbled via setrefs.c treewalk
nasyncplans Yes
first_partial_plan Yes
part_prune_index Yes
MergeAppend
plan Yes
apprelids Yes
mergeplans Indirect Jumbled via setrefs.c treewalk
numCols Yes
sortColIdx Yes
sortOperators Yes
collations Yes
nullsFirst Yes
part_prune_index Yes
RecursiveUnion
plan Yes
wtParam Yes
numCols Yes
dupColIdx Yes
dupOperators Yes
dupCollations Yes
numGroups No Costing/selectivity information should be ignored
BitmapAnd
plan Yes
bitmapplans Indirect Jumbled via setrefs.c treewalk
BitmapOr
plan Yes
isshared Yes
bitmapplans Indirect Jumbled via setrefs.c treewalk
Scan (abstract)
plan Yes
scanrelid Yes
SeqScan
scan Yes
SampleScan
scan Yes
tablesample Yes
IndexScan
scan Yes
indexid Yes
indexqual Yes
indexqualorig Yes
indexorderby Yes
indexorderbyorig Yes
indexorderbyops Yes
indexorderdir Yes
IndexOnlyScan
scan Yes
indexid Yes
indexqual Yes
recheckqual Yes
indexorderby Yes
indextlist Yes
indexorderdir Yes
BitmapIndexScan
scan Yes
indexid Yes
isshared Yes
indexqual Yes
indexqualorig Yes
BitmapHeapScan
scan Yes
bitmapqualorig Yes
TidScan
scan Yes
tidquals Yes
TidRangeScan
scan Yes
tidrangequals Yes
SubqueryScan
scan Yes
subplan Indirect Jumbled via setrefs.c treewalk
scanstatus Yes
FunctionScan
scan Yes
functions Yes
funcordinality Yes
ValuesScan
scan Yes
values_lists Yes Fixed values get ignored since they are A_Const
TableFuncScan
scan Yes
tablefunc Yes
CteScan
scan Yes
ctePlanId Yes
cteParam Yes
NamedTuplestoreScan
scan Yes
enrname Yes
WorkTableScan
scan Yes
wtParam Yes
ForeignScan
scan Yes
operation Yes
resultRelation Yes
checkAsUser Yes
fs_server Yes
fdw_exprs Yes
fdw_private No Private data for the FDW
fdw_scan_tlist Yes
fdw_recheck_quals Yes
fs_relids Yes
fs_base_relids Yes
fsSystemCol Yes
CustomScan
scan Yes
flags Yes
custom_plans Yes
custom_exprs Yes
custom_private No Private data for the Custom Scan Provider
custom_scan_tlist Yes
custom_relids Yes
methods No Pointer to a static struct that can't be jumbled
Join (abstract)
plan Yes
jointype Yes
inner_unique Yes
joinqual Yes
NestLoop
join Yes
nestParams Yes
MergeJoin
join Yes
skip_mark_restore Yes
mergeclauses Yes
mergeFamilies Yes
mergeCollations Yes
mergeReversals Yes
mergeNullsFirst Yes
HashJoin
join Yes
hashclauses Yes
hashoperators Yes
hashcollations Yes
hashkeys Yes
Material
plan Yes
Memoize
plan Yes
numKeys Yes
hashOperators Yes
collations Yes
param_exprs Yes
singlerow Yes
binary_mode Yes
est_entries No Costing/selectivity information should be ignored
keyparamids Yes
Sort
plan Yes
numCols Yes
sortColIdx Yes
sortOperators Yes
collations Yes
nullsFirst Yes
IncrementalSort
sort Yes
nPresortedCols Yes
Group
plan Yes
numCols Yes
grpColIdx Yes
grpOperators Yes
grpCollations Yes
Agg
plan Yes
aggstrategy Yes
aggsplit Yes
numCols Yes
grpColIdx Yes
grpOperators Yes
grpCollations Yes
numGroups No Costing/selectivity information should be ignored
transitionSpace Yes
aggParams Yes
groupingSets Yes
chain Yes
WindowAgg
plan Yes
winref Yes
partNumCols Yes
partColIdx Yes
partOperators Yes
partCollations Yes
ordNumCols Yes
ordColIdx Yes
ordOperators Yes
ordCollations Yes
frameOptions Yes
startOffset Yes
endOffset Yes
runCondition Yes
runConditionOrig Yes
startInRangeFunc Yes
endInRangeFunc Yes
inRangeColl Yes
inRangeAsc Yes
inRangeNullsFirst Yes
topWindow Yes
Unique
plan Yes
numCols Yes
uniqColIdx Yes
uniqOperators Yes
uniqCollations Yes
Gather
plan Yes
num_workers Yes
rescan_param Yes
single_copy Yes
invisible Yes
initParam Yes
GatherMerge
plan Yes
num_workers Yes
rescan_param Yes
numCols Yes
sortColIdx Yes
sortOperators Yes
collations Yes
nullsFirst Yes
initParam Yes
Hash
plan Yes
hashkeys Yes
skewTable Yes
skewColumn Yes
skewInherit Yes
rows_total No Costing/selectivity information should be ignored
SetOp
plan Yes
cmd Yes
strategy Yes
numCols Yes
cmpColIdx Yes
cmpOperators Yes
cmpCollations Yes
cmpNullsFirst Yes
numGroups No Costing/selectivity information should be ignored
LockRows
plan Yes
rowMarks Yes PlanRowMark nodes are ignored for jumbling
epqParam Yes
Limit
plan Yes
limitOffset Yes Fixed OFFSET values get ignored since they are A_Const
limitCount Yes Fixed LIMIT values get ignored since they are A_Const
limitOption Yes
uniqNumCols Yes
uniqColIdx Yes
uniqOperators Yes
uniqCollations Yes