PostgreSQL查询代价估算(四)
来源:互联网 发布:有线电视有网络吗 编辑:程序博客网 时间:2024/06/15 11:45
1.1.1 两表连接的代价估算
1.1.1.1 归并连接的代价:final_cost_mergejoin
函数功能:
计算两个关系使用归并连接算法的花费。有些操作被缓存便于后续使用。内外表的可连接[1]的元组数决定着CPU的花费。
函数功能:
计算两个关系使用归并连接连接算法的花费。
对于mergejoin花费的计算,分为两个函数:
1. 一是initial_cost_mergejoin函数,初步估计mergejoin算法的花费,形成的结果会作为final_cost_mergejoin的入口参数(JoinCostWorkspace *workspace)传入final_cost_mergehjoin函数;
2. 二是final_cost_mergejoin函数,对mergejoin算法的花费进行计算,并决定是否选用物化操作优化mergejoin连接。
代码分析:
void
final_cost_mergejoin(PlannerInfo *root, MergePath *path,
JoinCostWorkspace *workspace,
SpecialJoinInfo *sjinfo)
{......
//计算mergequals、qpquals(otherrestriction clauses)的花费(mergequals是joinrestrictinfo的子部分)
cost_qual_ev
cost_qual_ev
qp_qual_cost.startup-= merge_qual_cost.startup;
qp_qual_cost.per_tuple-= merge_qual_cost.per_tuple;
//获取mergequals子句涉及的元组数,计算CPU花费的重要依据
//每个子句都有不同的选择率(clause_selectivity函数计算子句的选择率)
//approx_tuple_count函数计算归并子句(mergeclauses)中的各子句的选择率,这些选择率的积就是归并条件的总的选择率,总的选择率乘以内关系的元组数再乘以外关系的元组数,由此可以得到归并后的总的元组数(mergejointuples),将来要依据mergejointuples得出这些元组归并连接时的CPU花费
mergejointuples= approx_tuple_count(root,&path->jpath, mergeclauses);
//mergejoin算法,读入外表的一条元组,然后与内表的每个元组比较;如果外表有相等的元组,则内表需要多次读入,所以,重新扫描率总可能比1大
//如果外表键值是唯一的,则不存在内表需要重复读入的问题
if(IsA(outer_path, UniquePath))
rescannedtuples= 0;
else//否则,要考虑内表需要重复读入
{
rescannedtuples= mergejointuples - inner_path_rows;
if(rescannedtuples < 0)
rescannedtuples= 0;
}
rescanratio= 1.0 + (rescannedtuples / inner_path_rows);
//计算内表在考虑了重复读入的问题后的全部花费
bare_inner_cost= inner_run_cost * rescanratio;
//物化内表的花费
mat_inner_cost= inner_run_cost +
cpu_operator_cost* inner_path_rows * rescanratio;
//内表物化比内表重读花费小,则选择物化方式的优化
if(enable_material && mat_inner_cost < bare_inner_cost)
path->materialize_inner= true;
elseif (innersortkeys == NIL &&//内表无序且不支持mark/restore,选用物化
!ExecSupportsMarkRestore(inner_path->pathtype))
path->materialize_inner= true;
elseif (enable_material && innersortkeys != NIL &&//内表有序但排序空间不够,选用物化
relation_byte_size(inner_path_rows,inner_path->parent->width) >
(work_mem * 1024L))
path->materialize_inner= true;
else
path->materialize_inner= false;
if(path->materialize_inner)
run_cost+= mat_inner_cost;
else
run_cost+= bare_inner_cost;
//知道了选择率、元组数等,则可以计算CPU花费:
//1 归并的CPU的花费---进行比较的花费
startup_cost+= merge_qual_cost.startup;
startup_cost+= merge_qual_cost.per_tuple *
(outer_skip_rows+ inner_skip_rows * rescanratio);
run_cost+= merge_qual_cost.per_tuple * //进行比较的花费
((outer_rows- outer_skip_rows) +
(inner_rows - inner_skip_rows) * rescanratio);
//2 归并的CPU的花费—进行连接的花费
startup_cost+= qp_qual_cost.startup;
cpu_per_tuple= cpu_tuple_cost + qp_qual_cost.per_tuple;
run_cost+= cpu_per_tuple * mergejointuples; //进行连接的花费
path->jpath.path.startup_cost= startup_cost;
path->jpath.path.total_cost= startup_cost + run_cost;
}
调用关系图解:
1. final_cost_mergejoin函数被create_mergejoin_path函数调用,直至被add_paths_to_joinrel函数调用,完成两表连接的mergejoin连接算法的花费估算;
2. final_cost_mergejoin函数被sort_inner_and_outer、match_unsorted_outer这两个函数分别调用,用以应对多种情况(内外表是否有序)的连接操作。
[1] 比较是否可连接有CPU花费,比较的元组数目较多;进行连接也有CPU花费,连接的元组数通常少于比较时的数目
- PostgreSQL查询代价估算(四)
- PostgreSQL查询代价估算(一)
- PostgreSQL查询代价估算(二)
- PostgreSQL查询代价估算(三)
- PostgreSQL查询代价估算(五)
- PostgreSQL查询代价估算(六)
- PostgreSQL查询代价估算(七)
- PostgreSQL查询代价估算(八)
- PostgreSQL查询代价估算--目录
- (5)执行计划的代价估算
- 数据库查询代价估算优化的深度介绍
- PostgreSQL 数据操作和查询(四)
- PostgreSQL源码修改 ——查询优化(四)
- PostgreSQL源码修改 ——查询优化(四)
- PostgreSQL 数据类型介绍(四)
- PostgreSQL(四)存储结构
- MySQL 执行计划中代价估算的输出信息
- postgresql查询
- sizeof详解
- java.lang.UnsatisfiedLinkError: no webp-imageio in java.library.path
- 管理的本质
- osi参考模型 tcp/ip概念层
- Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 21 declared in li
- PostgreSQL查询代价估算(四)
- icmp协议
- PostgreSQL查询代价估算(五)
- TCP三次握手,四次挥手
- PostgreSQL查询代价估算(六)
- tcp重发机制,确认机制,窗口机制
- PostgreSQL查询代价估算(七)
- linux用户管理(1)----创建用户(adduser和useradd)和删除用户(userdel)
- Laravel-EloquentORM 进阶部分