PostgreSQL 的扩展pg_freespacemap

PostgreSQL 的扩展pg_freespacemap

pg_freespacemap 是 PostgreSQL 提供的一个内置扩展,用于查看表的空闲空间映射(Free Space Map, FSM)信息。这个扩展对于数据库性能调优和空间管理非常有用。

一 扩展概述

功能 :提供对表的空闲空间映射的直接访问
用途

  • 分析表的空间利用率
  • 识别空间浪费严重的表
  • 优化VACUUM和空间回收策略
  • 诊断膨胀问题

版本支持:PostgreSQL 8.4+(不同版本功能可能略有差异)

二、安装与启用

sql 复制代码
-- 创建扩展
CREATE EXTENSION pg_freespacemap;

-- 验证是否安装成功
SELECT * FROM pg_available_extensions WHERE name = 'pg_freespacemap';

输出示例:

sql 复制代码
white=# CREATE EXTENSION pg_freespacemap;
CREATE EXTENSION
white=# SELECT * FROM pg_available_extensions WHERE name = 'pg_freespacemap';
      name       | default_version | installed_version |             comment              
-----------------+-----------------+-------------------+----------------------------------
 pg_freespacemap | 1.2             | 1.2               | examine the free space map (FSM)
(1 row)

white=# 

三 主要功能函数

3.1 pg_freespace(relation regclass, blkno bigint)

返回特定表块的空闲空间字节数

sql 复制代码
-- 获取表'yewu1.t1'的第0块的空闲空间
SELECT pg_freespace('yewu1.t1'::regclass, 0);

输出示例:

sql 复制代码
white=# SELECT pg_freespace('yewu1.t1'::regclass, 0);
 pg_freespace 
--------------
            0
(1 row)

white=# 

3.2 pg_freespace(relation regclass)

返回表所有块的空闲空间信息

sql 复制代码
-- 获取表'test'的所有块空闲空间
SELECT * FROM pg_freespace('yewu1.t1'::regclass);

输出示例:

sql 复制代码
white=# SELECT * FROM pg_freespace('yewu1.t1'::regclass);
 blkno | avail 
-------+-------
     0 |     0
(1 row)

white=#

四 使用示例

示例1:分析表的空间利用率

sql 复制代码
-- 创建测试表
CREATE TABLE test_table (id serial, data text);
INSERT INTO test_table (data) SELECT generate_series(1,10000)::text;

-- 查看空闲空间分布
SELECT blkno, avail 
FROM pg_freespace('test_table'::regclass)
ORDER BY avail DESC
LIMIT 10;

输出示例:

sql 复制代码
white=# CREATE TABLE yewu1.test_table (id serial, data text);
CREATE TABLE
white=# INSERT INTO yewu1.test_table (data) SELECT generate_series(1,10000)::text;
INSERT 0 10000
white=# 
white=# -- 查看空闲空间分布
white=# SELECT blkno, avail 
white-# FROM pg_freespace('yewu1.test_table'::regclass)
white-# ORDER BY avail DESC
white-# LIMIT 10;
 blkno | avail 
-------+-------
     4 |    32
     2 |     0
     7 |     0
     9 |     0
     5 |     0
     6 |     0
     3 |     0
     8 |     0
     1 |     0
     0 |     0
(10 rows)

white=# 

示例2:识别空间浪费严重的表

sql 复制代码
-- 找出数据库中平均空闲空间最多的表
SELECT
    n.nspname AS schema,
    c.relname AS table,
    pg_size_pretty(pg_relation_size(c.oid)) AS size,
    (SELECT avg(avail) FROM pg_freespace(c.oid)) AS avg_free_space
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
ORDER BY avg_free_space DESC
LIMIT 10;

输出示例:

sql 复制代码
white=# SELECT
white-#     n.nspname AS schema,
white-#     c.relname AS table,
white-#     pg_size_pretty(pg_relation_size(c.oid)) AS size,
white-#     (SELECT avg(avail) FROM pg_freespace(c.oid)) AS avg_free_space
white-# FROM pg_class c
white-# JOIN pg_namespace n ON n.oid = c.relnamespace
white-# WHERE c.relkind = 'r'
white-# ORDER BY avg_free_space DESC
white-# LIMIT 10;
   schema   |         table         |  size   | avg_free_space 
------------+-----------------------+---------+----------------
 pg_catalog | pg_user_mapping       | 0 bytes |               
 pg_catalog | pg_subscription       | 0 bytes |               
 pg_catalog | pg_statistic_ext_data | 0 bytes |               
 yewu1      | test5                 | 0 bytes |               
 pg_catalog | pg_foreign_table      | 0 bytes |               
 yewu1      | test6                 | 0 bytes |               
 yewu1      | test2                 | 0 bytes |               
 yewu1      | test4                 | 0 bytes |               
 yewu1      | test3                 | 0 bytes |               
 pg_catalog | pg_inherits           | 0 bytes |               
(10 rows)

white=# 

五 输出解释

pg_freespace 函数输出

列名 类型 描述
blkno bigint 块号(从0开始)
avail int 该块中可用空间字节数

六 实际应用场景

场景1:定期空间监控

sql 复制代码
-- 创建监控视图
CREATE VIEW table_space_monitor AS
SELECT
    n.nspname AS schema,
    c.relname AS table,
    pg_size_pretty(pg_relation_size(c.oid)) AS size,
    (SELECT avg(avail) FROM pg_freespace(c.oid)) AS avg_free_bytes,
    round((SELECT sum(avail) FROM pg_freespace(c.oid)) * 100.0 / 
          NULLIF(pg_relation_size(c.oid), 0), 2) AS free_percent
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
AND pg_relation_size(c.oid) > 0;

输出示例:

sql 复制代码
white=# CREATE VIEW table_space_monitor AS
white-# SELECT
white-#     n.nspname AS schema,
white-#     c.relname AS table,
white-#     pg_size_pretty(pg_relation_size(c.oid)) AS size,
white-#     (SELECT avg(avail) FROM pg_freespace(c.oid)) AS avg_free_bytes,
white-#     round((SELECT sum(avail) FROM pg_freespace(c.oid)) * 100.0 / 
white(#           NULLIF(pg_relation_size(c.oid), 0), 2) AS free_percent
white-# FROM pg_class c
white-# JOIN pg_namespace n ON n.oid = c.relnamespace
white-# WHERE c.relkind = 'r'
white-# AND pg_relation_size(c.oid) > 0;
CREATE VIEW
white=# 
white=# select * from table_space_monitor;
       schema       |          table          |    size    |     avg_free_bytes     | free_percent 
--------------------+-------------------------+------------+------------------------+--------------
 public             | pgbench_accounts        | 128 MB     |   107.0799220272904483 |         1.31
 public             | pgbench_branches        | 8192 bytes | 0.00000000000000000000 |         0.00
 public             | pgbench_history         | 13 MB      |     4.3969465648854962 |         0.05
 public             | pgbench_tellers         | 8192 bytes | 0.00000000000000000000 |         0.00
 pg_catalog         | pg_type                 | 128 kB     |    54.0000000000000000 |         0.66
 pg_catalog         | pg_statistic            | 208 kB     |    17.2307692307692308 |         0.21
 pg_catalog         | pg_authid               | 8192 bytes |  5984.0000000000000000 |        73.05
 yewu1              | t2                      | 440 kB     |   140.2181818181818182 |         1.71
 yewu1              | test10                  | 8192 bytes | 0.00000000000000000000 |         0.00
 pg_catalog         | pg_attribute            | 568 kB     |     1.3521126760563380 |         0.02
 pg_catalog         | pg_proc                 | 832 kB     |    74.1538461538461538 |         0.91
 pg_catalog         | pg_attrdef              | 8192 bytes | 0.00000000000000000000 |         0.00
 yewu1              | t1                      | 8192 bytes | 0.00000000000000000000 |         0.00
 pg_catalog         | pg_constraint           | 24 kB      |  1546.6666666666666667 |        18.88
 pg_catalog         | pg_index                | 40 kB      |    32.0000000000000000 |         0.39
 pg_catalog         | pg_operator             | 112 kB     |   162.2857142857142857 |         1.98
 pg_catalog         | pg_opfamily             | 16 kB      |   272.0000000000000000 |         3.32
 pg_catalog         | pg_opclass              | 24 kB      |   842.6666666666666667 |        10.29
 pg_catalog         | pg_am                   | 8192 bytes |  7392.0000000000000000 |        90.23
 pg_catalog         | pg_amop                 | 56 kB      |    59.4285714285714286 |         0.73
 pg_catalog         | pg_amproc               | 40 kB      |   921.6000000000000000 |        11.25
 pg_catalog         | pg_language             | 8192 bytes |  7648.0000000000000000 |        93.36
 pg_catalog         | pg_aggregate            | 16 kB      |   128.0000000000000000 |         1.56
 pg_catalog         | pg_rewrite              | 120 kB     |   157.8666666666666667 |         1.93
 pg_catalog         | pg_trigger              | 8192 bytes | 0.00000000000000000000 |         0.00
 pg_catalog         | pg_description          | 344 kB     |    97.4883720930232558 |         1.19
 pg_catalog         | pg_cast                 | 16 kB      |  2208.0000000000000000 |        26.95
 pg_catalog         | pg_namespace            | 8192 bytes |  7584.0000000000000000 |        92.58
 pg_catalog         | pg_conversion           | 16 kB      |   224.0000000000000000 |         2.73
 pg_catalog         | pg_depend               | 128 kB     | 0.00000000000000000000 |         0.00
 pg_catalog         | pg_database             | 8192 bytes |  7008.0000000000000000 |        85.55
 pg_catalog         | pg_tablespace           | 8192 bytes |  7936.0000000000000000 |        96.88
 pg_catalog         | pg_auth_members         | 8192 bytes |  8000.0000000000000000 |        97.66
 pg_catalog         | pg_shdescription        | 8192 bytes |  7936.0000000000000000 |        96.88
 pg_catalog         | pg_ts_config            | 8192 bytes |  5024.0000000000000000 |        61.33
 pg_catalog         | pg_ts_config_map        | 24 kB      |    64.0000000000000000 |         0.78
 pg_catalog         | pg_ts_dict              | 8192 bytes |  4000.0000000000000000 |        48.83
 pg_catalog         | pg_ts_parser            | 8192 bytes |  8032.0000000000000000 |        98.05
 pg_catalog         | pg_ts_template          | 8192 bytes |  7616.0000000000000000 |        92.97
 pg_catalog         | pg_extension            | 8192 bytes |  8032.0000000000000000 |        98.05
 pg_catalog         | pg_init_privs           | 32 kB      |    16.0000000000000000 |         0.20
 pg_catalog         | pg_collation            | 224 kB     |   265.1428571428571429 |         3.24
 pg_catalog         | pg_range                | 8192 bytes |  7776.0000000000000000 |        94.92
 pg_catalog         | pg_sequence             | 8192 bytes | 0.00000000000000000000 |         0.00
 information_schema | sql_features            | 64 kB      |   704.0000000000000000 |         8.59
 information_schema | sql_implementation_info | 8192 bytes |  7296.0000000000000000 |        89.06
 information_schema | sql_parts               | 8192 bytes |  7328.0000000000000000 |        89.45
 information_schema | sql_sizing              | 8192 bytes |  6176.0000000000000000 |        75.39

场景2:自动VACUUM决策

sql 复制代码
-- 找出需要VACUUM的表(空闲空间超过30%)
SELECT 
    n.nspname AS schema,
    c.relname AS table,
    round((SELECT sum(avail) FROM pg_freespace(c.oid)) * 100.0 / 
          NULLIF(pg_relation_size(c.oid), 0), 2) AS free_percent
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
AND (SELECT sum(avail) FROM pg_freespace(c.oid)) > 
    0.3 * pg_relation_size(c.oid)
ORDER BY free_percent DESC;

输出示例:

sql 复制代码
white=# SELECT 
white-#     n.nspname AS schema,
white-#     c.relname AS table,
white-#     round((SELECT sum(avail) FROM pg_freespace(c.oid)) * 100.0 / 
white(#           NULLIF(pg_relation_size(c.oid), 0), 2) AS free_percent
white-# FROM pg_class c
white-# JOIN pg_namespace n ON n.oid = c.relnamespace
white-# WHERE c.relkind = 'r'
white-# AND (SELECT sum(avail) FROM pg_freespace(c.oid)) > 
white-#     0.3 * pg_relation_size(c.oid)
white-# ORDER BY free_percent DESC;
       schema       |          table          | free_percent 
--------------------+-------------------------+--------------
 pg_catalog         | pg_ts_parser            |        98.05
 pg_catalog         | pg_extension            |        98.05
 pg_catalog         | pg_auth_members         |        97.66
 pg_catalog         | pg_shdescription        |        96.88
 pg_catalog         | pg_tablespace           |        96.88
 pg_catalog         | pg_range                |        94.92
 pg_catalog         | pg_language             |        93.36
 pg_catalog         | pg_ts_template          |        92.97
 pg_catalog         | pg_namespace            |        92.58
 pg_catalog         | pg_am                   |        90.23
 information_schema | sql_parts               |        89.45
 information_schema | sql_implementation_info |        89.06
 pg_catalog         | pg_database             |        85.55
 information_schema | sql_sizing              |        75.39
 pg_catalog         | pg_authid               |        73.05
 pg_catalog         | pg_ts_config            |        61.33
 pg_catalog         | pg_ts_dict              |        48.83
(17 rows)

white=# 

七 注意事项

  1. 性能影响:频繁查询FSM会对系统性能产生一定影响,建议在非高峰期使用
  2. 权限要求:需要超级用户或表所有者权限
  3. 实时性:FSM信息不是实时更新的,VACUUM操作后会更新
  4. 外部表:不适用于外部表
  5. TOAST表:需要单独检查TOAST表的空闲空间

八 与VACUUM的关系

  1. VACUUM会更新FSM信息
  2. FSM大小由参数max_fsm_pagesmax_fsm_relations控制
  3. 可以使用VACUUM VERBOSE查看FSM更新情况
sql 复制代码
-- 调整FSM参数(需要重启)
ALTER SYSTEM SET max_fsm_pages = 200000;
ALTER SYSTEM SET max_fsm_relations = 10000;

九 故障排查

问题1:扩展无法创建

解决方案

sql 复制代码
-- 检查是否在正确数据库创建
SELECT current_database();

-- 检查扩展是否已存在
SELECT * FROM pg_available_extensions WHERE name = 'pg_freespacemap';

-- 以超级用户身份创建
\c - postgres
CREATE EXTENSION pg_freespacemap;

问题2:查询返回空结果

可能原因

  • 表太小(小于1个块)
  • 没有空闲空间
  • 权限不足

验证方法

sql 复制代码
-- 检查表大小
SELECT pg_size_pretty(pg_relation_size('table_name'));

-- 检查权限
\z table_name

通过合理使用pg_freespacemap扩展,数据库管理员可以有效监控和管理PostgreSQL表的空间使用情况,优化存储效率并减少不必要的空间浪费。

相关推荐
黑马金牌编程18 小时前
Jenkins的Linux与window部署方式
linux·运维·windows·jenkins·持续集成·cicd
web安全工具库18 小时前
告别刀耕火种:用 Makefile 自动化 C 语言项目编译
linux·运维·c语言·开发语言·数据库·算法·自动化
金纬软件119 小时前
电脑监控软件有哪些?企业监控软件应该怎么选?
大数据·运维
DechinPhy19 小时前
Ubuntu挂载新硬盘
linux·运维·服务器·ubuntu
lht63193561219 小时前
Ubuntu Server 系统安装图形界面远程工具(RDP)
linux·运维·ubuntu
disanleya19 小时前
怎样安全地开启MySQL远程管理权限?
数据库·mysql
云计算练习生19 小时前
linux shell编程实战 02 变量与交互式输入
linux·运维·shell编程·shell 变量
Dovis(誓平步青云)19 小时前
《简易制作 Linux Shell:详细分析原理、设计与实践》
linux·运维·服务器
【非典型Coder】19 小时前
Statement和PreparedStatement区别
数据库
爱宇阳20 小时前
Linux 教程:如何查看服务器当前目录中的文件
linux·运维·github