开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言 🌟

在日常的数据库管理中,你是否遇到过这样的情况:删除了大量数据后,发现磁盘空间并没有减少?或者,数据删除后,索引占用的空间依旧庞大,影响了查询效率。这是因为在PostgreSQL中,DELETE 语句虽然删除了数据,但索引的存储空间不会自动释放。这篇文章将带你深入探讨如何在删除数据时同时释放索引空间,从而优化数据库的存储与查询效率。


📜 目录

  1. DELETE真的删除了吗? 🤔
  2. 删除数据后如何释放索引空间? 📉
  3. 示例演示:释放索引空间的具体操作 💻
  4. 拓展知识:VACUUM 与 VACUUM FULL的区别 🧹
  5. 总结与最佳实践 🎉

1. DELETE真的删除了吗? 🤔

在PostgreSQL中,当你执行 DELETE 操作时,数据实际上并没有真正从磁盘中消失。而是被标记为“已删除”,等待后台的清理进程(VACUUM)来回收空间。这种机制主要是为了支持MVCC(多版本并发控制),以确保在高并发环境中能为各个事务提供一致的数据视图。

不过呢,索引的数据块不会自动回收,即使索引指向的行数据被标记为删除,索引块仍然存在!这意味着,如果不进行额外操作,索引会占据越来越多的空间,导致数据库性能下降。


2. 删除数据后如何释放索引空间? 📉

要想彻底释放索引所占的空间,最常用的方式是使用VACUUM命令来清理无效数据。PostgreSQL中有以下几种常用的清理方式:

2.1 VACUUM 🧹

VACUUM 是PostgreSQL内置的清理命令,用来回收被标记为“已删除”数据的存储空间。但要注意的是,普通的 VACUUM 操作仅仅是回收被删除数据的空间,索引空间不会自动回收

VACUUM table_name;

2.2 VACUUM FULL 🧹💯

如果你不仅想释放数据空间,还要释放索引空间,那么可以使用**VACUUM FULL。这个命令会重建表和索引**,从而释放未使用的磁盘空间。不过,VACUUM FULL会持有表的排他锁,操作期间表将不可写入,因此不适合频繁操作的大表。

VACUUM FULL table_name;

2.3 REINDEX 重新索引 🔄

REINDEX 是用于重建索引的命令。在删除大量数据后,索引仍会残留大量空闲块,而执行REINDEX命令可以清理这些空闲块,释放不再使用的空间。可以选择单个索引进行重建,也可以重建整个表的所有索引。

-- 重建指定索引
REINDEX INDEX index_name;

-- 重建表的所有索引
REINDEX TABLE table_name;

注意REINDEXVACUUM FULL 一样,可能会对性能造成一定的影响,因此需要选择在业务低峰期操作。


3. 示例演示:释放索引空间的具体操作 💻

下面我们来演示一下删除数据并释放索引空间的完整流程。假设我们有一张员工信息表employees,其中包含大量数据和索引。

3.1 准备数据

首先,创建employees表,并插入一些数据。

CREATE TABLE employees (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    department VARCHAR(50)
);

-- 插入10000条数据
INSERT INTO employees (name, department)
SELECT 'Employee ' || i, 'Dept' || (i % 10)
FROM generate_series(1, 10000) AS i;

创建一个索引来加速基于department字段的查询:

CREATE INDEX idx_department ON employees(department);

3.2 删除部分数据

接下来,删除部门编号为Dept5的所有员工记录。

DELETE FROM employees WHERE department = 'Dept5';

这时,可以发现数据被删除了,但索引占用的空间并没有减少。

3.3 使用 VACUUM FULL 释放空间

执行VACUUM FULL来清理表和索引空间。

VACUUM FULL employees;

使用 VACUUM FULL 后,可以通过查看表的存储空间使用情况,确认索引和表空间都得到了释放。可以执行如下查询来查看表和索引的大小:

SELECT pg_size_pretty(pg_total_relation_size('employees')) AS total_size,
       pg_size_pretty(pg_indexes_size('employees')) AS index_size;

这样,我们就成功释放了索引所占用的空间。


4. 拓展知识:VACUUM 与 VACUUM FULL的区别 🧹

  • VACUUM:标记为“已删除”的数据会被清理,释放存储空间,但并不会收缩索引,也不会减小表的物理大小。适合日常的维护操作。

  • VACUUM FULL:不仅会清理已删除的数据,还会进行物理表的重组和索引空间的释放。该命令适用于磁盘空间紧张的情况,但会锁住表,期间无法进行写操作,因此应避免频繁使用。

  • AutoVacuum:PostgreSQL还提供了AutoVacuum自动清理机制,通常会自动运行VACUUM。不过,该机制不会执行VACUUM FULL,因此无法主动释放索引空间。


5. 总结与最佳实践 🎉

总结

在PostgreSQL中,删除数据并不会自动释放索引空间,需要通过VACUUM FULLREINDEX命令来手动释放。对于频繁执行DELETE操作的表,定期进行索引重建和VACUUM FULL清理,可以避免索引冗余和性能下降。

最佳实践

  1. 定期使用VACUUM:在业务低峰期,定期对表进行VACUUM,防止表膨胀。
  2. 合理使用VACUUM FULL:避免频繁使用VACUUM FULL,对于小表可以适当安排。
  3. 监控表和索引大小:通过pg_indexes_size()pg_total_relation_size()监控表和索引的大小,及时识别并释放无效空间。
  4. 善用AutoVacuum:默认情况下AutoVacuum是开启的,但可以根据需求调整清理频率。

掌握这些方法后,你就可以高效管理PostgreSQL的存储空间,从而提高数据库性能!希望这篇文章对你有所帮助,记得多多实践哦!

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐