|
Chapter 18. 索引开销计算函数
每种索引访问模式都必须提供一个用于规划器/优化器的开销计算函数. 这个函数的过程 OID 在访问模式在 pg_am 里的 记录的 amcostestimate 字段里给出.
amcostestimate 函数收到一列 WHERE 子句,这些子句被认为对索引是有用的. 这个函数本身必须返回计算出来的访问索引的开销和 WHERE 子句的选择性( 也就是说,在索引扫描过程中主表元组中要被捡索出来的部分). 对于简单的情况, 几乎所有开销计算器的工作都可以通过调用优化器里标准的过程来完成, 需要一个 amcostestimate 函数的原因是允许索引访问模式提供一些索引类型相关的信息, 这样就有可能改进标准的计算(预计). 每个 amcostestimate 函数都必须有下面的名字: void amcostestimate (Query *root, RelOptInfo *rel, IndexOptInfo *index, List *indexQuals, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation); 前面四个参数是输入:
最后四个参数是通过引用传递的输出:
请注意开销计算函数必须用 C 写,而不是 SQL 或者任何可以用的过程语言. 因为他们必须访问规划器/优化器的内部数据结构. 索引访问开销应该以 src/backend/optimizer/path/costsize.c 里面使用的单位计算: 一次顺序磁盘存储块抓取开销为 1.0, 一次非顺序抓取的开销为 random_page_cost, 并且处理一个索引记录的开销通常应该当做 cpu_index_tuple_cost (它是一个可以由用户调节的优化器参数).另外,应该用一个 cpu_operator_cost 的合适的倍数作为索引处理期间任何激活的比较操作符 (尤其是计算 indexQuals (索引查询)自己). 访问开销应该包含所有与扫描索引本身的相关的磁盘和 CPU 开销, 而不是检索或处理被索引标识的主表索引的开销. "启动开销"是全部索引开销中在我们开始抓取第一条记录之前必须消耗的开销. 对于大多数索引,这部分可以当做零, 但是一个有着比较高启动开销的索引类型可能希望把这个值设置为非零. indexSelectivity (索引选择性)应该设置为在索引扫描过程中主表记录里将被检索出的部分. 如果是一个松索引的场合, 这个数字将明显地比实际传递给给出的资格条件的记录部分高. indexCorrelation 应该设置为索引顺序和表顺序的相关性系数(范围在 -1.0 和 1.0 之间).它用于调整从主表中抓取元组的开销的计算. 开销计算 一次典型的开销计算器将象下面这样进行:
开销计算器的例子可以在 src/backend/utils/adt/selfuncs.c 找到. 通常,一个 amcostestimate 函数的 pg_proc 记录会看起来象 prorettype = 0 pronargs = 8 proargtypes = 0 0 0 0 0 0 0 0 我们将零("opaque")用于所有参数, 因为它们都没有在 pg_type 里面已知的类型. |