作者:由 Tom Lane 写于 2000-01-24.
注意:这些内容最后必须成为关于书写新的索引访问方式的更大的一章的一部分.
注意:在 Postgres 7.0 以前,使用的是另外一种注册与索引相关的开销计算函数的构造.
每个 amcostestimate 函数都必须有下面的名字:
void amcostestimate (Query *root, RelOptInfo *rel, IndexOptInfo *index, List *indexQuals, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity);前面四个参数是输入:
索引访问开销应该以 src/backend/optimizer/path/costsize.c 里面使用的单位计算:一次顺序磁盘存储块抓取开销为 1.0,一次非顺序抓取的开销为 random_page_cost,并且处理一个索引记录的开销通常应该当做 cpu_index_tuple_cost (它是一个可以由用户调节的优化器参数).另外,应该用一个cpu_operator_cost 的合适的倍数作为索引处理期间任何激活的比较操作符(尤其是计算 indexQuals (索引查询)自己).
访问开销应该包含所有与扫描索引本身的相关的磁盘和 CPU 开销,而不是检索或处理被索引标识的主表索引的开销.
"启动开销"是全部索引开销中在我们开始抓取第一条记录之前必须消耗的开销.对于大多数索引,这部分可以当做零,但是一个有着比较高启动开销的索引类型可能希望把这个值设置为非零.
indexSelectivity (索引选择性)应该设置为在索引扫描过程中主表记录里将被检索出的部分.如果是一个松索引的场合,这个数字将明显地比实际传递给给出的资格条件的记录部分高.
一次典型的开销计算器将象下面这样进行:
*indexSelectivity = clauselist_selectivity(root, indexQuals, lfirsti(rel->relids));计算(估计)在扫描过程中将要被访问的索引记录数.对于许多索引类型,这个数字等于 indexSelectivity 乘以索引里面的记录数量,但是它可以更多.(请注意索引在页面里的大小和记录可以从结构 IndexOptInfo 里获得.)
计算(估计)在扫描过程中将要被检索出的索引页面数.这个数字可以只是 indexSelectivity 乘以以页面数计算的索引的大小.
计算索引访问开销.一个常间的计算器可以这样做:
/* * Our generic assumption is that the index pages will be read * sequentially, so they have cost 1.0 each, not random_page_cost. * Also, we charge for evaluation of the indexquals at each index tuple. * All the costs are assumed to be paid incrementally during the scan * (我们一般性的假设是索引页面将被顺序读入, * 因此它们每个的开销为1.0,没有 random_page_cose. * 同样,我们计算每条索引记录的索引条件的开销. * 所有开销都假设是在扫描过程中逐步递增的. */ *indexStartupCost = 0; *indexTotalCost = numIndexPages + (cpu_index_tuple_cost + cost_qual_eval(indexQuals)) * numIndexTuples;
通常,一个 amcostestimate 函数的 pg_proc 记录会看起来象
prorettype = 0 pronargs = 7 proargtypes = 0 0 0 0 0 0 0我们将零("opaque")用于所有参数,因为它们没有一个有在 pg_type 里面已知的类型.