PostgreSQL中获取Tuple的分区键值函数是什么

62次阅读
没有评论

共计 10312 个字符,预计需要花费 26 分钟才能阅读完成。

这篇文章主要介绍“PostgreSQL 中获取 Tuple 的分区键值函数是什么”,在日常操作中,相信很多人在 PostgreSQL 中获取 Tuple 的分区键值函数是什么问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PostgreSQL 中获取 Tuple 的分区键值函数是什么”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!

一、数据结构

ModifyTable
通过插入、更新或删除,将子计划生成的行应用到结果表。

/* ----------------
 * ModifyTable node -
 * Apply rows produced by subplan(s) to result table(s),
 * by inserting, updating, or deleting.
 *  通过插入、更新或删除,将子计划生成的行应用到结果表。 *
 * If the originally named target table is a partitioned table, both
 * nominalRelation and rootRelation contain the RT index of the partition
 * root, which is not otherwise mentioned in the plan. Otherwise rootRelation
 * is zero. However, nominalRelation will always be set, as it s the rel that
 * EXPLAIN should claim is the INSERT/UPDATE/DELETE target.
 *  如果最初命名的目标表是分区表,则 nominalRelation 和 rootRelation 都包含分区根的 RT 索引,计划中没有另外提到这个索引。 *  否则,根关系为零。但是,总是会设置名义关系,nominalRelation 因为 EXPLAIN 应该声明的 rel 是 INSERT/UPDATE/DELETE 目标关系。 * 
 * Note that rowMarks and epqParam are presumed to be valid for all the
 * subplan(s); they can t contain any info that varies across subplans.
 *  注意,rowMarks 和 epqParam 被假定对所有子计划有效;
 *  它们不能包含任何在子计划中变化的信息。 * ----------------
 */
typedef struct ModifyTable
 Plan plan;
 CmdType operation; /*  操作类型;INSERT, UPDATE, or DELETE */
 bool canSetTag; /*  是否需要设置 tag?do we set the command tag/es_processed? */
 Index nominalRelation; /*  用于 EXPLAIN 的父 RT 索引;Parent RT index for use of EXPLAIN */
 Index rootRelation; /*  根 Root RT 索引(如目标为分区表);Root RT index, if target is partitioned */
 bool partColsUpdated; /*  更新了层次结构中的分区关键字;some part key in hierarchy updated */
 List *resultRelations; /* RT 索引的整型链表;integer list of RT indexes */
 int resultRelIndex; /*  计划链表中第一个 resultRel 的索引;index of first resultRel in plan s list */
 int rootResultRelIndex; /*  分区表根索引;index of the partitioned table root */
 List *plans; /*  生成源数据的计划链表;plan(s) producing source data */
 List *withCheckOptionLists; /*  每一个目标表均具备的 WCO 链表;per-target-table WCO lists */
 List *returningLists; /*  每一个目标表均具备的 RETURNING 链表;per-target-table RETURNING tlists */
 List *fdwPrivLists; /*  每一个目标表的 FDW 私有数据链表;per-target-table FDW private data lists */
 Bitmapset *fdwDirectModifyPlans; /* FDW DM 计划索引位图;indices of FDW DM plans */
 List *rowMarks; /* rowMarks 链表;PlanRowMarks (non-locking only) */
 int epqParam; /* EvalPlanQual 再解析使用的参数 ID;ID of Param for EvalPlanQual re-eval */
 OnConflictAction onConflictAction; /* ON CONFLICT action */
 List *arbiterIndexes; /*  冲突仲裁器索引表;List of ON CONFLICT arbiter index OIDs */
 List *onConflictSet; /* SET for INSERT ON CONFLICT DO UPDATE */
 Node *onConflictWhere; /* WHERE for ON CONFLICT UPDATE */
 Index exclRelRTI; /* RTI of the EXCLUDED pseudo relation */
 List *exclRelTlist; /*  已排除伪关系的投影列链表;tlist of the EXCLUDED pseudo relation */
} ModifyTable;

ResultRelInfo
ResultRelInfo 结构体
每当更新一个现有的关系时,我们必须更新关系上的索引,也许还需要触发触发器。ResultRelInfo 保存关于结果关系所需的所有信息,包括索引。

/*
 * ResultRelInfo
 * ResultRelInfo 结构体
 *
 * Whenever we update an existing relation, we have to update indexes on the
 * relation, and perhaps also fire triggers. ResultRelInfo holds all the
 * information needed about a result relation, including indexes.
 *  每当更新一个现有的关系时,我们必须更新关系上的索引,也许还需要触发触发器。 * ResultRelInfo 保存关于结果关系所需的所有信息,包括索引。 * 
 * Normally, a ResultRelInfo refers to a table that is in the query s
 * range table; then ri_RangeTableIndex is the RT index and ri_RelationDesc
 * is just a copy of the relevant es_relations[] entry. But sometimes,
 * in ResultRelInfos used only for triggers, ri_RangeTableIndex is zero
 * and ri_RelationDesc is a separately-opened relcache pointer that needs
 * to be separately closed. See ExecGetTriggerResultRel.
 *  通常,ResultRelInfo 是指查询范围表中的表;
 * ri_RangeTableIndex 是 RT 索引,而 ri_RelationDesc 只是相关 es_relations[]条目的副本。 *  但有时,在只用于触发器的 ResultRelInfos 中,ri_RangeTableIndex 为零(NULL), *  而 ri_RelationDesc 是一个需要单独关闭单独打开的 relcache 指针。 *  具体可参考 ExecGetTriggerResultRel 结构体。 */
typedef struct ResultRelInfo
 NodeTag type;
 /* result relation s range table index, or 0 if not in range table */
 //RTE 索引
 Index ri_RangeTableIndex;
 /* relation descriptor for result relation */
 // 结果 / 目标 relation 的描述符
 Relation ri_RelationDesc;
 /* # of indices existing on result relation */
 // 目标关系中索引数目
 int ri_NumIndices;
 /* array of relation descriptors for indices */
 // 索引的关系描述符数组(索引视为一个 relation)
 RelationPtr ri_IndexRelationDescs;
 /* array of key/attr info for indices */
 // 索引的键 / 属性数组
 IndexInfo **ri_IndexRelationInfo;
 /* triggers to be fired, if any */
 // 触发的索引
 TriggerDesc *ri_TrigDesc;
 /* cached lookup info for trigger functions */
 // 触发器函数(缓存)
 FmgrInfo *ri_TrigFunctions;
 /* array of trigger WHEN expr states */
 //WHEN 表达式状态的触发器数组
 ExprState **ri_TrigWhenExprs;
 /* optional runtime measurements for triggers */
 // 可选的触发器运行期度量器
 Instrumentation *ri_TrigInstrument;
 /* FDW callback functions, if foreign table */
 //FDW 回调函数
 struct FdwRoutine *ri_FdwRoutine;
 /* available to save private state of FDW */
 // 可用于存储 FDW 的私有状态
 void *ri_FdwState;
 /* true when modifying foreign table directly */
 // 直接更新 FDW 时为 T
 bool ri_usesFdwDirectModify;
 /* list of WithCheckOption s to be checked */
 //WithCheckOption 链表
 List *ri_WithCheckOptions;
 /* list of WithCheckOption expr states */
 //WithCheckOption 表达式链表
 List *ri_WithCheckOptionExprs;
 /* array of constraint-checking expr states */
 // 约束检查表达式状态数组
 ExprState **ri_ConstraintExprs;
 /* for removing junk attributes from tuples */
 // 用于从元组中删除 junk 属性
 JunkFilter *ri_junkFilter;
 /* list of RETURNING expressions */
 //RETURNING 表达式链表
 List *ri_returningList;
 /* for computing a RETURNING list */
 // 用于计算 RETURNING 链表
 ProjectionInfo *ri_projectReturning;
 /* list of arbiter indexes to use to check conflicts */
 // 用于检查冲突的仲裁器索引的列表
 List *ri_onConflictArbiterIndexes;
 /* ON CONFLICT evaluation state */
 //ON CONFLICT 解析状态
 OnConflictSetState *ri_onConflict;
 /* partition check expression */
 // 分区检查表达式链表
 List *ri_PartitionCheck;
 /* partition check expression state */
 // 分区检查表达式状态
 ExprState *ri_PartitionCheckExpr;
 /* relation descriptor for root partitioned table */
 // 分区 root 根表描述符
 Relation ri_PartitionRoot;
 /* Additional information specific to partition tuple routing */
 // 额外的分区元组路由信息
 struct PartitionRoutingInfo *ri_PartitionInfo;
} ResultRelInfo;

PartitionRoutingInfo
PartitionRoutingInfo 结构体
分区路由信息, 用于将元组路由到表分区的结果关系信息。

/*
 * PartitionRoutingInfo
 * PartitionRoutingInfo -  分区路由信息
 * 
 * Additional result relation information specific to routing tuples to a
 * table partition.
 *  用于将元组路由到表分区的结果关系信息。 */
typedef struct PartitionRoutingInfo
 /*
 * Map for converting tuples in root partitioned table format into
 * partition format, or NULL if no conversion is required.
 *  映射,用于将根分区表格式的元组转换为分区格式,如果不需要转换,则转换为 NULL。 */
 TupleConversionMap *pi_RootToPartitionMap;
 /*
 * Map for converting tuples in partition format into the root partitioned
 * table format, or NULL if no conversion is required.
 *  映射,用于将分区格式的元组转换为根分区表格式,如果不需要转换,则转换为 NULL。 */
 TupleConversionMap *pi_PartitionToRootMap;
 /*
 * Slot to store tuples in partition format, or NULL when no translation
 * is required between root and partition.
 *  以分区格式存储元组的 slot. 在根分区和分区之间不需要转换时为 NULL。 */
 TupleTableSlot *pi_PartitionTupleSlot;
} PartitionRoutingInfo;

TupleConversionMap
TupleConversionMap 结构体, 用于存储元组转换映射信息.

typedef struct TupleConversionMap
 TupleDesc indesc; /*  源行类型的描述符;tupdesc for source rowtype */
 TupleDesc outdesc; /*  结果行类型的描述符;tupdesc for result rowtype */
 AttrNumber *attrMap; /*  输入字段的索引信息,0 表示 NULL;indexes of input fields, or 0 for null */
 Datum *invalues; /*  析构源数据的工作空间;workspace for deconstructing source */
 bool *inisnull; // 是否为 NULL 标记数组
 Datum *outvalues; /*  构造结果的工作空间;workspace for constructing result */
 bool *outisnull; //null 标记
} TupleConversionMap;

二、源码解读

FormPartitionKeyDatum 函数获取 Tuple 的分区键值, 返回键值 values[]数组和是否为 null 标记 isnull[]数组.

/* ----------------
 * FormPartitionKeyDatum
 * Construct values[] and isnull[] arrays for the partition key
 * of a tuple.
 *  构造 values[]数组和 isnull[]数组
 *
 * pd Partition dispatch object of the partitioned table
 * pd  分区表的分区分发器 (dispatch) 对象
 *
 * slot Heap tuple from which to extract partition key
 * slot  从其中提前分区键的 heap tuple
 *
 * estate executor state for evaluating any partition key
 * expressions (must be non-NULL)
 * estate  解析分区键表达式 (必须非 NULL) 的执行器状态
 *
 * values Array of partition key Datums (output area)
 *  分区键 Datums 数组(输出参数)
 * isnull Array of is-null indicators (output area)
 * is-null 标记数组(输出参数)
 *
 * the ecxt_scantuple slot of estate s per-tuple expr context must point to
 * the heap tuple passed in.
 * estate 的 per-tuple 上下文的 ecxt_scantuple 必须指向传入的 heap tuple
 * ----------------
 */
static void
FormPartitionKeyDatum(PartitionDispatch pd,
 TupleTableSlot *slot,
 EState *estate,
 Datum *values,
 bool *isnull)
 ListCell *partexpr_item;
 int i;
 if (pd- key- partexprs != NIL   pd- keystate == NIL)
 {
 /* Check caller has set up context correctly */
 // 检查调用者是否已正确配置内存上下文
 Assert(estate != NULL 
 GetPerTupleExprContext(estate)- ecxt_scantuple == slot);
 /* First time through, set up expression evaluation state */
 // 第一次进入, 配置表达式解析器状态
 pd- keystate = ExecPrepareExprList(pd- key- partexprs, estate);
 }
 partexpr_item = list_head(pd- keystate);// 获取分区键表达式状态
 for (i = 0; i   pd- key- partnatts; i++)// 循环遍历分区键
 {
 AttrNumber keycol = pd- key- partattrs[i];// 分区键属性编号
 Datum datum;// typedef uintptr_t Datum;sizeof(Datum) == sizeof(void *) == 4 or 8
 bool isNull;// 是否 null
 if (keycol != 0)// 编号不为 0
 {
 /* Plain column; get the value directly from the heap tuple */
 // 扁平列, 直接从堆元组中提取值
 datum = slot_getattr(slot, keycol,  isNull);
 }
 else
 {
 /* Expression; need to evaluate it */
 // 表达式, 需要解析
 if (partexpr_item == NULL)// 分区键表达式状态为 NULL, 报错
 elog(ERROR,  wrong number of partition key expressions
 // 获取表达式值
 datum = ExecEvalExprSwitchContext((ExprState *) lfirst(partexpr_item),
 GetPerTupleExprContext(estate),
  isNull);
 // 切换至下一个
 partexpr_item = lnext(partexpr_item);
 }
 values[i] = datum;// 赋值
 isnull[i] = isNull;
 }
 if (partexpr_item != NULL)// 参数设置有误? 报错
 elog(ERROR,  wrong number of partition key expressions

 * slot_getattr - fetch one attribute of the slot s contents.
 * slot_getattr -  提取 slot 中的某个属性值
 */
static inline Datum
slot_getattr(TupleTableSlot *slot, int attnum,
 bool *isnull)
 AssertArg(attnum   0);
 if (attnum   slot- tts_nvalid)
 slot_getsomeattrs(slot, attnum);
 *isnull = slot- tts_isnull[attnum - 1];
 return slot- tts_values[attnum - 1];

 * This function forces the entries of the slot s Datum/isnull arrays to be
 * valid at least up through the attnum th entry.
 *  这个函数强制 slot 的 Datum/isnull 数组的条目至少在 attnum 的第一个条目上是有效的。
 */
static inline void
slot_getsomeattrs(TupleTableSlot *slot, int attnum)
 if (slot- tts_nvalid   attnum)
 slot_getsomeattrs_int(slot, attnum);

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-20发表,共计10312字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)