ccfdb=> create table test(id int, info text, crt_time timestamp);
ccfdb=> insert into test select generate_series(1, 10000), md5(cast(random() as text)), now();
ccfdb=> explain select * from test;
QUERY PLAN
-----------------------------------------------------------
Seq Scan on test (cost=0.00..218.00 rows=10000 width=45)
ccfdb=> select relpages, reltuples from pg_class where relname = 'test';
relpages | reltuples
----------+-----------
118 | 10000
复制
#seq_page_cost=1.0 #measured on an arbitrary scale
#random_page_cost=4.0 #same scale as above
#cpu_tuple_cost=0.01 #same scale as above
#cpu_index_tuple_cost=0.005 #same scale as above
回到刚才的例子,表 test 有 10000 条数据分布在 118 个磁盘页,评估时间是(磁盘页*seq_page_cost)+(扫描行*cpu_tuple_cost)。
默认 seq_page_cost 是1.0,cpu_tuple_cost 是 0.01,所以评估值是(118 * 1.0) + (10000 * 0.01) = 218。
ccfdb=> create index idx_test_id on test(id);
CREATE INDEX
ccfdb=>
ccfdb=> explain select * from test where id < 1000;
QUERY PLAN
-----------------------------------------------------------------------------
Index Scan using idx_test_id on test (cost=0.00..44.75 rows=1000 width=45)
Index Cond: (id < 1000)
(2 rows)
ccfdb=> explain select * from test where id < 1000 or id > 9000 ;
QUERY PLAN
------------------------------------------------------------------------------------
Bitmap Heap Scan on test (cost=40.45..188.45 rows=1900 width=45)
Recheck Cond: ((id < 1000) OR (id > 9000))
-> BitmapOr (cost=40.45..40.45 rows=2000 width=0)
-> Bitmap Index Scan on idx_test_id (cost=0.00..19.75 rows=1000 width=0)
Index Cond: (id < 1000)
-> Bitmap Index Scan on idx_test_id (cost=0.00..19.75 rows=1000 width=0)
Index Cond: (id > 9000)
(7 rows)
复制
Bitmap Index Scan 和 Index Scan 扫描的区别很明显:
Index scan: 输出的是 tuple,它先扫描索引块,然后得到 rowid 扫描数据块得到目标记录。一次只读一条索引项,那么一个 PAGE 面有可能被多次访问.Bitmap index scan; 输出的是索引条目,并不是行的数据,输出索引条目后,交给上一个节点 bitmap heap scan(之间可能将索引条目根据物理排列顺序进行排序)。一次性将满足条件的索引项全部取出,然后交给 bitmap heap scan节点,并在内存中进行排序, 根据取出的索引项访问表数据。
2、GS_WLM_SESSION_INFO系统表显示数据库主节点执行作业结束后的负载管理记录。此数据是从内核中转储到系统表中的数据。当设置GUC参数enable_resource_record为on时,系统会定时(周期为3分钟)将内核中query信息导入GS_WLM_SESSION_QUERY_INFO_ALL系统表。
--登陆postgres数据库,通过sql语句统计Topsql列表。
select
substr(query, 1, 60) as sub_query, --截取sql语句的1-60字段进行分组统计
dbname, --数据库名
count(1) as count, --sql调用频次
round(avg(duration), 2) as avg_duration, --sql平均执行时间
query_plan,
max(queryid) as query_id --根据queryid查询具体SQL
from gs_wlm_session_info
where dbname in ('dzyz') --数据库名
and start_time > '2023-10-31 14:00:00' --开始时间
and finish_time < '2023-10-31 18:00:00' --结束时间
group by 1,2,5;
--使用上例sql查出来TOP SQL的queryid,查询完整的sql语句
select query from gs_wlm_session_info where queryid='xxxxx';