一、执行计划
1、解释
- 查询计划的结构是一棵树,由不同类型的节点组成。
- 最底层是扫描节点,用于从表中获取原始数据行。
- 如果需要对数据进行连接、聚合、排序等操作,在扫描节点之上会有相应的节点。
- EXPLAIN输出的每一行对应树中的一个节点,显示节点的类型和执行成本估算。
- 第一行是整个查询计划的估计总执行成本,优化器的目标就是最小化这个成本。
2、案例
t1=# explain select * from t3;
QUERY PLAN
--------------------------------------------------------
Seq Scan on t3 (cost=0.00..54.08 rows=1408 width=371)
(1 row)
-
估计的启动成本。这是在输出阶段开始之前所花费的时间,例如,在排序节点中进行排序的时间。
-
估计的总成本。这是在假设计划节点运行到完成的情况下得出的,即检索到所有可用行。
-
此计划节点估计输出的行数。同样,假设节点运行到完成。
-
该计划节点输出行的估计平均宽度(以字节为单位)。
-
成本是以规划器的成本参数确定的任意单位来衡量的。传统的做法是以磁盘页面获取的单位来衡量成本;也就是说,seq_page_cost通常设置为1.0,其他成本参数相对于该值进行设置。
-
上层节点的成本包括其所有子节点的成本
-
行数值不是计划节点处理或扫描的行数,而是节点发出的行数。这通常少于扫描的数目,因为在节点上应用的任何WHERE子句条件都会进行过滤。理想情况下,顶层行数估计值将接近查询实际返回、更新或删除的行数。
3、Cost值计算
计算1
t1=# SELECT relname, relpages FROM pg_class WHERE relname = 't3';
relname | relpages
---------+----------
t3 | 40
(1 row)
t1=# SELECT pg_relation_size('t3') / 8192 AS pages;
pages
-------
40
(1 row)
t1=# select count(*) from t3;
count
-------
1408
(1 row)
t1=# explain select * from t3;
QUERY PLAN
--------------------------------------------------------
Seq Scan on t3 (cost=0.00..54.08 rows=1408 width=371)
(1 row)
t1=# show cpu_tuple_cost;
cpu_tuple_cost
----------------
0.01
(1 row)
t1=# show seq_page_cost;
seq_page_cost
---------------
1
(1 row)
cost=(disk pages read * seq_page_cost) + (rows scanned * cpu_tuple_cost)=(401)+(14080.01)=40+14.08=54.08
计算2
t1=# explain select count(*) from t2;
QUERY PLAN
--------------------------------------------------------------------------------------
Finalize Aggregate (cost=25121.88..25121.89 rows=1 width=8)
-> Gather (cost=25121.67..25121.88 rows=2 width=8)
Workers Planned: 2
-> Partial Aggregate (cost=24121.67..24121.68 rows=1 width=8)
-> Parallel Seq Scan on t2 (cost=0.00..23370.73 rows=300373 width=0)
(5 rows)
t1=# select count(*) from t2;
count
--------
720896
(1 row)
t1=# SELECT relname, relpages FROM pg_class WHERE relname = 't2';
relname | relpages
---------+----------
t2 | 20367
(1 row)
- 第五行
(sequential_page_cost * pages) + (cpu_tuple_cost * tuples)
= (1.0 * 20367) + (0.01 * 300373)
= 20367 + 3003.73
= 23370.73
- 第四行
startup_cost = child_startup_cost
total_cost = child_total_cost + cpu_operator_cost * rows
- child_startup_cost: 子节点的启动成本。
- child_total_cost: 子节点的总成本。
- cpu_operator_cost: 在每个元组(行)上执行聚合操作的 CPU 成本。
- rows: 估计需要处理的元组(行)数。
t1=# show cpu_operator_cost;
cpu_operator_cost
-------------------
0.0025
(1 row)
startup_cost = 0.00
total_cost = 23370.73 + (0.0025 * 300373) = 23370.73 + 750.93 = 24121.66
- 第二行
t1=# show parallel_setup_cost;
parallel_setup_cost
---------------------
1000
(1 row)
parallel_setup_cost = 1000.0 (默认值)
Partial Aggregate 节点的成本范围: cost=24121.67..24121.68
cpu_tuple_cost = 0.01 (默认值)
rows = 2 (估计需要处理的元组数)
startup_cost = child_startup_cost + parallel_setup_cost
total_cost = startup_cost + cpu_tuple_cost * rows
startup_cost = 24121.67 + 1000.0 = 25121.67
total_cost = 25121.67 + (0.01 * 2) = 25121.67 + 0.02 = 25121.69
最后修改时间:2024-03-29 17:50:35
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




