本节介绍代价计算和相关计算公式。
代价计算模型
操作成本 | 默认值 | 说明 |
---|---|---|
seq_page_cost | 1.0 | 顺序扫描一个页面的成本。 |
random_page_cost | 4.0 | 随机扫描一个页面的成本。 |
cpu_tuple_cost | 0.01 | CPU处理一行的成本。 |
cpu_index_tuple_cost | 0.005 | CPU处理一个索引项的成本。 |
cpu_operator_cost | 0.0025 | CPU处理每个函数或操作符的成本。 |
全表扫描
postgres=# explain select * from test where id <1000;
QUERY PLAN
----------------------------------------------------------
Seq Scan on test (cost=0.00..1693.00 rows=5680 width=4)
Filter: (id < 1000)
(2 rows)
postgres=# select relpages,reltuples from pg_class where relname='test';
relpages | reltuples
------------+-----------
443 | 100000
(1 row)
计算公式如下:
- TOTAL_COST = CPU代价 + IO代价
- CPU代价 = cpu_tuple_cost * reltuples + cpu_operator_cost * reltuples
- CPU代价 = 0.01 * 100000 + 0.0025 * 100000 = 1250.0
- IO代价 = seq_page_cost * relpages
- IO代价 = 1.0 * 443 = 443
- TOTAL_COST = 1250 + 443 = 1693
索引扫描
postgres=# explain select * from test where id =1414;
QUERY PLAN
-------------------------------------------------------------------------------
Index Only Scan using test_id_idx on test (cost=0.29..72.66 rows=30 width=4)
Index Cond: (id = 1414)
(2 rows)
计算公式如下:
- RUN_COST = CPU代价 + IO代价
- CPU代价 = 索引 CPU代价 + 表 CPU代价
- 索引CPU代价 = 选择率 * 索引行数 * (cpu_index_tuple_cost + cpu_operator_cost )
- 表 CPU代价 = 选择率 * 数据行数 * cpu_tuple_cost
索引CPU代价计算
postgres=# select most_common_freqs[array_position((most_common_vals::text)::real[],1414::real)] from pg_stats where tablename ='test';
most_common_freqs
-------------------
0.0003
## 选择率 = 0.0003
postgres=# select relpages,reltuples from pg_class where relname='test_id_idx';
relpages | reltuples
----------+-----------
276 | 100000
## 索引行数 = 100000 ,索引页面数 = 276
postgres=# select relpages,reltuples from pg_class where relname='test';
relpages | reltuples
----------+-----------
443 | 100000
## 表行数 = 100000 ,表页面数 = 443
通过以上计算示例得出CPU代价如下:
- 索引CPU代价 = 0.0003 * 100000 * (0.0025 + 0.005) = 0.22500000
- 表CPU代价 = 0.0003 * 100000 * 0.01 = 0.300000
- CPU代价 = 0.300000 + 0.22500000 = 0.52500000
索引IO代价计算
索引IO代价 = ceil (选择率 * 索引页面数) * random_page_cost
表IO代价 = max_io_cost + 相关系数 * 相关系数 * (min_io_cost – max_io_cost)
max_io_cost = 选择率 * 数据行数 * random_page_cost = 120
min_io_cost = 1 * random_page_cost + (ceil(选择率 * 表页面数) - 1) * seq_page_cost = 4
postgres=# select correlation from pg_stats where tablename ='test';
correlation
-------------
0.670535
相关系数 = 0.670535
IO代价 = 4 + 67.844406397900 = 71.844406397900
通过以上计算示例得出IO代价如下:
- RUN_COST = 71.844406397900 + 0.52500000 = 72.369406397900
- START_COST = 0.29
- TOTAL_COST = 72.369406397900 + 0.29 = 72.659406397900 ≈ 72.66