一文讲清楚PostgreSQL表膨胀

文章目录

一、表膨胀的概念

1. 是什么

表膨胀是指PostgreSQL数据库中的表和索引所占用的文件系统空间,在有效数据量并未发生大的变化的情况下,不断增大的现象。

2. 为什么产生

表膨胀的产生主要源于PostgreSQL的多版本并发控制(MVCC)机制 。在这种机制下,当一条记录被更新或删除时,原始记录不会立即从磁盘上移除,而是被标记为不可见,新的记录(在更新的情况下)会被添加到表中。 随着时间的推移,如果不进行适当的维护,这些"死"行(即被标记为不可见的旧版本数据,对所有事务不可见但是所占空间不会归还系统)会不断累积,导致表膨胀。此外,频繁的更新和删除操作、未提交的事务以及不合理的表设计等因素也会加剧表膨胀。

3. 有什么影响

表膨胀会导致存储资源的浪费 ,增加磁盘的存储成本。同时,随着表膨胀的加剧,数据库在查询和操作数据时会变得更加缓慢,因为需要扫描更多的数据页面来读取同样多的数据行,从而增加了读写所需的IO和CPU资源。此外,表膨胀还会降低shared buffer中的命中率,进一步增加访问磁盘的可能性,从而降低性能。

二、如何查询表膨胀

要查询PostgreSQL中的表膨胀情况,可以使用以下方法和工具:

1. 使用SQL查询

通过SQL查询可以获取表和索引的大小、活跃行数以及死行数等信息。例如,可以使用pg_size_pretty(pg_table_size(table_name))来查看表的大小,使用pg_stat_all_tables视图来查询表中的死行和活跃行数。

(1)查所有表

下面的代码是查看数据库中所有数据表的表膨胀情况,并返回膨胀率前100名的结果。其中对于每张table,n_dead_tup是死区,n_live_tup是活区,dead_tup_ratio是膨胀率。

java 复制代码
SELECT
    schemaname||'.'||relname as table_name,
    pg_size_pretty(pg_relation_size(schemaname||'.'||relname)) as table_size,
    n_dead_tup,
    n_live_tup,
    round(n_dead_tup * 100 / (n_live_tup + n_dead_tup),2) AS dead_tup_ratio
FROM
    pg_stat_all_tables
WHERE
    n_dead_tup >= 1
ORDER BY dead_tup_ratio DESC
LIMIT 100;

(2)查单张表

下面的代码是查看指定数据表的表膨胀情况。

java 复制代码
SELECT
    schemaname||'.'||relname as table_name,
    pg_size_pretty(pg_relation_size(schemaname||'.'||relname)) as table_size,
    n_dead_tup,
    n_live_tup,
    round(n_dead_tup * 100 / (n_live_tup + n_dead_tup),2) AS dead_tup_ratio
FROM
    pg_stat_all_tables
WHERE
    relname = 'table_name';

2. 使用pgstattuple插件

pgstattuple插件可以提供更详细的表膨胀信息,包括表的总大小、元组(行)数、死元组数以及死元组占用的总大小等。通过安装并使用该插件,可以更方便地评估表的膨胀状况。

三、如何消除表膨胀

解决PostgreSQL表膨胀问题的方法主要包括以下几种:

1. 执行VACUUM操作

VACUUM操作可以清理数据库中的死元组并释放空间。PostgreSQL提供了自动的autovacuum 机制,可以使用定时调度任务定期自动执行VACUUM操作以防止表膨胀。但是,在某些情况下,可能需要手动执行VACUUM操作或调整autovacuum的相关参数以确保其能够及时清理死元组。

bash 复制代码
vacuum tablename

2. 执行VACUUM FULL操作

VACUUM FULL操作不仅会清理死元组,还会对表进行碎片整理并尝试减小其在磁盘上的大小。但是,VACUUM FULL会锁定整个表,在高并发场景下需谨慎使用,并尽量在业务低峰期执行。

bash 复制代码
vacuum full tablename

3. 使用ANALYZE操作

在VACUUM操作之后,建议执行ANALYZE操作以更新表和索引的统计信息,从而优化查询计划并提升查询性能。

bash 复制代码
ANALYZE table_name

或者,你也可以使用 VACUUM 命令的 ANALYZE 选项,这样可以在一个命令中同时完成清理死元组和更新统计信息的操作:

bash 复制代码
VACUUM ANALYZE table_name

4. 合理设计表结构

合理设计表结构可以减少表膨胀的发生。例如,可以根据实际业务需求合理选择字段的数据类型,避免使用不必要的大数据类型;去除冗余数据,确保数据的有效性和准确性;为频繁查询的列创建索引,避免不必要的索引导致的膨胀等。还可以创建分区表,避免所有数据都存入到主表中,导致查询性能低。

5. 定期监控和预警

建立健全的数据库监控体系,对表的膨胀情况进行实时监测并设置阈值告警。一旦发现表膨胀现象,可以快速响应并采取相应的措施进行处理。

四、总结

PostgreSQL表膨胀是一个常见且复杂的问题,它会对数据库的性能和存储资源产生负面影响。通过深入了解表膨胀的原因、查询方法以及解决方案,我们可以有效地控制和管理表膨胀问题,提升数据库的性能和管理效率。在实际操作中,我们需要结合监控数据和分析工具,建立科学的数据库管理流程,并遵循最佳实践来避免空间膨胀带来的负面影响,确保系统的高效运行。这不仅能为企业节省成本,还能为用户带来更好的体验。

不停地计算工作效率,才能找出自己的问题所在,立即执行,绝不逃脱,先紧后松,只有掌握自己的工作,才能掌握时间。

相关推荐
寒月霜华41 分钟前
JavaWeb后端-MySQL
数据库·mysql
Fuly10241 小时前
大模型的记忆与管理及长期记忆实现方式
数据库·人工智能·rag
weixin_307779131 小时前
C#程序实现将Teradata的存储过程转换为Azure Synapse Dedicated SQL pool的存储过程
数据库·数据分析·c#·云计算·azure
折翼的恶魔2 小时前
SQL 189 统计有未完成状态的试卷的未完成数和未完成率
数据库·sql
yangmf20402 小时前
如何使用 INFINI Gateway 增量迁移 ES 数据
大数据·数据库·elasticsearch·搜索引擎·gateway
运维李哥不背锅3 小时前
Ansible 的条件语句与循环详解
数据库·ansible
梦里不知身是客113 小时前
hive的SQL语句练习2
hive·hadoop·sql
曾凡宇先生3 小时前
OpenEuler中mysql这是在执行 MySQL 密码重置操作时出现的 “找不到mysqld_safe命令” 的错误场景。
数据库·mysql
梦里不知身是客114 小时前
hive的SQL练习3
hive·hadoop·sql
方二华4 小时前
6 mysql源码中的查询逻辑
数据库·mysql