60.6. 索引成本估算功能

amcostestimate函数提供了描述可能的索引扫描的信息,包括已确定可与该索引一起使用的 WHERE 和 ORDER BY 子句的列表。它必须返回对访问索引的成本以及 WHERE 子句的选择性(即在索引扫描期间将检索的父表行的分数)的估计值。对于简单的情况,成本估算器的几乎所有工作都可以通过在优化器中调用标准例程来完成;具有amcostestimate函数的目的是允许索引访问方法提供特定于索引类型的知识,以防可能会改善标准估计值。

每个amcostestimate函数必须具有签名:

void
amcostestimate (PlannerInfo *root,
                IndexPath *path,
                double loop_count,
                Cost *indexStartupCost,
                Cost *indexTotalCost,
                Selectivity *indexSelectivity,
                double *indexCorrelation,
                double *indexPages);

前三个参数是 Importing:

最后五个参数是按引用传递输出:

请注意,成本估算功能必须用 C 编写,而不用 SQL 或任何可用的过程语言编写,因为它们必须访问计划程序/优化程序的内部数据结构。

索引访问成本应使用src/backend/optimizer/path/costsize.c所使用的参数来计算:Sequences 磁盘块获取的成本为seq_page_cost,非 Sequences 磁盘获取的成本为random_page_cost,处理一个索引行的成本通常应为cpu_index_tuple_cost。此外,对于索引处理期间调用的任何比较运算符(特别是对 indexquals 的求值),应收取cpu_operator_cost的适当倍数。

访问成本应包括与扫描索引本身相关的所有磁盘和 CPU 成本,但不包括检索或处理由索引标识的父表行的成本。

“启动成本”是总扫描成本中必须首先花费的一部分,我们才能开始获取第一行。对于大多数索引,可以将其视为零,但是启动成本较高的索引类型可能希望将其设置为非零。

当* loop_count *大于 1 时,返回的数字应该是对索引的任何一次扫描所期望的平均值。

Cost Estimation

典型的成本估算器将按以下步骤进行:

*indexSelectivity = clauselist_selectivity(root, path->indexquals,
                                           path->indexinfo->rel->relid,
                                           JOIN_INNER, NULL);
/*
 * Our generic assumption is that the index pages will be read
 * sequentially, so they cost seq_page_cost each, not random_page_cost.
 * Also, we charge for evaluation of the indexquals at each index row.
 * All the costs are assumed to be paid incrementally during the scan.
 */
cost_qual_eval(&index_qual_cost, path->indexquals, root);
*indexStartupCost = index_qual_cost.startup;
*indexTotalCost = seq_page_cost * numIndexPages +
    (cpu_index_tuple_cost + index_qual_cost.per_tuple) * numIndexTuples;

但是,以上未考虑跨重复索引扫描的索引读取摊销。

成本估算器功能的示例可以在src/backend/utils/adt/selfuncs.c中找到。

上一章 首页 下一章