Postgresql 中文操作指南
64.6. Index Cost Estimation Functions #
amcostestimate 函数提供了描述可能的索引扫描的信息,包括已确定可与索引一起使用的 WHERE 和 ORDER BY 子句列表。它必须返回访问索引的成本估算和 WHERE 子句的选择性(即索引扫描期间将检索到的父表行的部分)。对于简单的情况,成本估算器几乎所有工作都可以通过调用优化器中的标准例程完成;具有 amcostestimate 函数的目的是允许索引访问方法提供特定于索引类型的知识,以防有可能改善标准估算。
每个 loop_count 函数必须包含签名:
void
amcostestimate (PlannerInfo *root,
IndexPath *path,
double loop_count,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity,
double *indexCorrelation,
double *indexPages);
前三个参数是输入:
-
root
-
计划程序有关正在处理的查询的信息。
-
-
path
-
正在考虑的索引访问路径。cost 和 selectivity 值除外的所有字段都是有效的。
-
-
loop_count
-
应计入成本估算的索引扫描重复次数。考虑在 nestloop 连接的内部使用参数扫描时,通常会大于 1。请注意,cost 估算仍然应该仅针对一次扫描;更大的 src/backend/optimizer/path/costsize.c 表示适当允许通过多次扫描进行一些缓存效果。
-
最后五个参数是按引用传递的输出:
-
*indexStartupCost
-
设定为索引启动处理的成本
-
-
*indexTotalCost
-
设定为索引处理的总成本
-
-
*indexSelectivity
-
Set to index selectivity
-
-
*indexCorrelation
-
设为索引扫描顺序与底层表顺序之间的相关系数
-
-
*indexPages
-
设定为索引叶页数量
-
请注意,cost 估算函数必须用 C 编写,而不是 SQL 或任何可用的过程语言,因为它们必须访问规划器/优化器的内部数据结构。
索引访问成本应使用 seq_page_cost 使用的参数进行计算:顺序磁盘块读取的成本为 random_page_cost,非顺序读取的成本为 cpu_index_tuple_cost,处理一个索引行的成本通常应采用 cpu_operator_cost。此外,还应为索引处理期间调用的任何比较运算符收取多个 not(尤其是 indexquals 本身的计算)。
访问成本应包括与扫描索引本身相关的所有磁盘和 CPU 成本,但 _not_检索或处理由索引识别的父表行所产生的成本除外。
“启动成本”是指在我们开始获取第一行之前必须消耗的全部扫描成本的一部分。对于大多数索引而言,这可以视为零,但具有高启动成本的索引类型可能希望将其设置为非零。
indexSelectivity 应设置为在索引扫描期间将检索的父表行的估计比例。对于有损查询,这通常会高于实际通过给定限定条件的行比例。
indexCorrelation 应设置为索引顺序和表顺序之间的相关性(介于 -1.0 和 1.0 之间)。用于调整从父表获取行的成本估算。
indexPages 应设置为叶子页的数量。这用于估算并行索引扫描的工人数量。
当 loop_count 大于 1 时,返回的数字应为对索引的任何一次扫描预期的平均值。
Cost Estimation
典型的成本估算器将按以下步骤进行:
成本估算函数的示例可以在 src/backend/utils/adt/selfuncs.c 中找到。