如何不使用PL/pgSQL动态查询,通过纯SQL获取PostgreSQL表主键列的总大小
纯SQL实现主键列总大小计算
当然有办法!你完全可以用纯SQL来实现这个需求,不需要依赖PL/pgSQL的动态查询。下面是两种可靠的实现方案:
方案一:利用JSONB提取主键列(推荐)
这个方法通过将行转换为JSON,提取出主键对应的字段后计算大小,逻辑清晰且兼容性好:
WITH pk_columns AS ( -- 获取目标表的所有主键列名数组 SELECT array_agg(a.attname) AS pk_col_names FROM pg_index i JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) WHERE i.indrelid = 'public.my_test'::regclass AND i.indisprimary ) SELECT COALESCE(SUM( pg_column_size( -- 提取每行的主键列组成的JSONB对象 jsonb_extract_path( pg_row_to_json(t), VARIADIC pk_col_names ) ) ), 0) AS total_primary_key_size FROM public.my_test t, pk_columns;
原理说明:
- 先用CTE
pk_columns查询系统表,拿到目标表的主键列名数组。 - 对表中每一行,用
pg_row_to_json把整行转为JSON格式。 - 用
jsonb_extract_path结合VARIADIC关键字,传入主键列名数组,提取出仅包含主键列的JSONB对象。 - 用
pg_column_size计算这个JSONB对象的大小(等同于该行所有主键列的大小之和),最后求和所有行的结果,COALESCE确保空表返回0而非NULL。
方案二:利用HStore提取主键列
如果你的环境中已经启用了hstore扩展,也可以用这种方式:
-- 先确保hstore扩展已启用(首次使用需执行) -- CREATE EXTENSION IF NOT EXISTS hstore; WITH pk_columns AS ( SELECT array_agg(a.attname) AS pk_col_names FROM pg_index i JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) WHERE i.indrelid = 'public.my_test'::regclass AND i.indisprimary ) SELECT COALESCE(SUM(pg_column_size(hstore(t) #> pk_col_names)), 0) AS total_primary_key_size FROM public.my_test t, pk_columns;
原理说明:
- 同样先获取主键列名数组。
- 用
hstore(t)把行转为键值对格式的hstore对象。 - 用
#>操作符提取主键列对应的hstore子集,计算其大小后求和。
这两种方案都和你原来的PL/pgSQL逻辑完全一致:都是逐行计算所有主键列的大小之和,再汇总所有行的结果,而且完全不需要动态SQL。
内容的提问来源于stack exchange,提问作者Oto Shavadze
相关产品推荐
相关产品推荐

