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 中找到。