1.1.1 单表扫描方式的代价估算
每种单表扫描方式、单表扫描方式的花费估算函数,都被set_plain_rel_pathlist函数调用,用以求解单表扫描的最优路径。
1.1.1.1 顺序扫描的代价:cost_seqscan
函数功能:
计算一个关系的顺序扫描方式的花费。依据代价估算模型“总代价 = I/O代价 + CPU代价”,计算从存储系统读入数据的IO花费和元组从页面中解析的CPU花费。
代码分析:
void
cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info)
{……
if (!enable_seqscan) // set_plain_rel_pathlist函数没有任何条件限制,直接生成了顺序扫描路径。如果禁用了顺序扫描,则给顺序扫描路径的启动花费加一个巨大的数值,使得生成的顺序扫描路径因花费大而不被选择;后续其他估算花费的函数,都类似处理
startup_cost += disable_cost;
//获取顺序扫描每页的读取花费;PostgreSQL从表空间中读取数据,区分了顺序读和随机读两种情况,顺序扫描采用了顺序读的获取每页顺序读取的花费
get_tablespace_page_costs(baserel->reltablespace, NULL, &spc_seq_page_cost);
//单表扫描,每页读取花费和读取的页数乘积,是IO消耗
run_cost += spc_seq_page_cost * baserel->pages;//IO花费依赖页面数
//每个元组的CPU消耗,从页面中分解元组的花费
get_restriction_qual_cost(root, baserel, param_info, &qpqual_cost);
startup_cost += qpqual_cost.startup;
cpu_per_tuple = cpu_tuple_cost + qpqual_cost.per_tuple; //每条元组的CPU花费
run_cost += cpu_per_tuple * baserel->tuples; //每条元组的CPU花费乘以元组数
//CPU花费依赖元组数
path->startup_cost = startup_cost;
path->total_cost = startup_cost + run_cost;
//最后的总的花费是:启动花费+总的IO花费+总的CPU花费
}
调用关系图解:
![PostgreSQL查询代价估算(二) - 那海蓝蓝 - 那海蓝蓝的博客 PostgreSQL查询代价估算(二) - 那海蓝蓝 - 那海蓝蓝的博客](http://img1.ph.126.net/1Lf6DYTBsSn_BqVusdt9fQ==/6598169278285638199.jpg)
1. cost_seqscan函数被创建顺序扫描路径的函数create_seqscan_path调用;
2. cost_seqscan函数还会被vacuum_rel函数逐层调用;用以完成系统的整理工作(整理工作也需要“优化”比较耗费)。