PostgreSQL性能优化:如何定期清理无用索引以释放磁盘空间(索引膨胀监控)
文章目录一、为什么需要清理无用索引1. 资源浪费2. 性能损耗3. 索引膨胀Index Bloat二、第一步识别从未使用的索引1. 启用索引统计前提2. 查询未使用索引3. 排除约束类索引三、第二步评估“低效”索引非零但极少使用1. 计算索引使用效率2. 结合查询日志分析四、第三步检测索引膨胀Bloat1. 使用社区脚本估算膨胀率方法一使用 pgstattuple 扩展精确但锁表方法二使用轻量级估算脚本推荐五、第四步安全删除无用索引1. 删除前 checklist2. 执行删除3. 验证删除效果六、第五步重建膨胀索引而非删除1. 重建命令2. 自动化重建策略七、建立自动化监控与治理机制1. 创建监控视图2. 设置告警3. 定期巡检脚本Shell psql八、最佳实践总结开发规范建议在 PostgreSQL 的长期运行中索引数量往往会随着业务迭代不断增长。然而并非所有索引都被有效利用——有些是历史遗留、有些因查询模式变更而失效、有些甚至从未被使用过。这些“僵尸索引”不仅浪费宝贵的磁盘空间还会拖慢 DML 操作INSERT/UPDATE/DELETE因为每次数据变更都需同步更新所有相关索引。更严重的是PostgreSQL 的 MVCC 机制会导致索引膨胀Index Bloat——当表数据频繁更新或删除时索引中的 dead tuples 无法及时回收使得索引物理大小远超实际需求进一步加剧 I/O 压力与查询延迟。本文将系统性地阐述如何识别、评估、安全删除无用索引并建立自动化监控与治理机制帮助你持续优化数据库存储效率与性能。一、为什么需要清理无用索引1. 资源浪费磁盘空间每个索引都是独立的物理结构占用与表相当甚至更多的空间内存缓存索引页会进入 shared_buffers 和 OS cache挤占热数据空间WAL 日志索引变更产生额外 WAL增加主从复制负担。2. 性能损耗写放大每新增一个索引INSERT/UPDATE/DELETE需多一次索引维护优化器负担过多索引使查询计划选择更复杂可能选错执行路径VACUUM 压力需扫描更多索引清理 dead tuples。3. 索引膨胀Index Bloat当表发生UPDATE或DELETE时旧索引项不会立即删除而是标记为 dead若autovacuum不及时dead tuples 积累索引体积膨胀膨胀后的索引导致更多随机 I/O更低的缓存命中率更长的查询时间。 经验数据生产环境中10%~30% 的索引可能从未被使用。二、第一步识别从未使用的索引PostgreSQL 提供了索引使用统计信息可精准定位“零访问”索引。1. 启用索引统计前提确保postgresql.conf中已开启track_counts on # 默认开启 track_io_timing off # 可选无需重启但统计信息从开启后才开始累积。2. 查询未使用索引SELECTschemanameASschema,tablenameAStable,indexnameASindex,pg_size_pretty(pg_relation_size(quote_ident(schemaname)||.||quote_ident(indexname)))ASindex_size,idx_tup_read,-- 索引扫描返回的行数Index Scanidx_tup_fetch-- 通过索引获取的堆元组数Index Only Scan Bitmap Heap ScanFROMpg_stat_user_indexesWHEREidx_tup_read0ANDidx_tup_fetch0ORDERBYpg_relation_size(quote_ident(schemaname)||.||quote_ident(indexname))DESC;关键条件idx_tup_read 0 AND idx_tup_fetch 0注意该统计基于自上次统计重置以来的数据排除对象主键PRIMARY KEY和唯一约束UNIQUE索引即使未用于查询也用于约束校验外键引用的索引用于级联操作加速。3. 排除约束类索引-- 获取所有约束索引WITHconstraint_indexesAS(SELECTconindidASindex_oidFROMpg_constraintWHEREcontypeIN(p,u,f)-- primary, unique, foreign key)SELECTn.nspnameASschema,c.relnameAStable,i.relnameASindex,pg_size_pretty(pg_relation_size(i.oid))ASsizeFROMpg_index idxJOINpg_class iONi.oididx.indexrelidJOINpg_class cONc.oididx.indrelidJOINpg_namespace nONn.oidc.relnamespaceLEFTJOINconstraint_indexes ciONci.index_oidi.oidWHEREci.index_oidISNULL-- 非约束索引AND(SELECTidx_tup_readidx_tup_fetchFROMpg_stat_user_indexesWHEREindexrelidi.oid)0ORDERBYpg_relation_size(i.oid)DESC;✅ 此结果集中的索引可安全评估删除。三、第二步评估“低效”索引非零但极少使用有些索引虽有少量访问但收益远低于维护成本。1. 计算索引使用效率SELECTschemaname,tablename,indexname,pg_size_pretty(pg_relation_size(indexrelid))ASindex_size,idx_tup_read,idx_tup_fetch,idx_scan,-- 索引被扫描次数ROUND((idx_tup_readidx_tup_fetch)*100.0/NULLIF(idx_scan,0),2)ASavg_rows_per_scanFROMpg_stat_user_indexesWHEREidx_scan0ORDERBYpg_relation_size(indexrelid)DESC;低效特征idx_scan很高但avg_rows_per_scan极低如 10→ 可能走错索引idx_scan极低如 10 次/天但索引很大1GB→ 收益不足。2. 结合查询日志分析使用pg_stat_statements查看哪些查询实际使用了该索引-- 需先启用 pg_stat_statementsCREATEEXTENSIONIFNOTEXISTSpg_stat_statements;SELECTquery,calls,total_exec_time,rowsFROMpg_stat_statementsWHEREqueryLIKE%INDEX_NAME%-- 替换为实际索引名需解析执行计划ORDERBYtotal_exec_timeDESC; 更准确方式通过EXPLAIN (ANALYZE, BUFFERS)确认执行计划是否使用目标索引。四、第三步检测索引膨胀Bloat即使索引被使用也可能因膨胀而效率低下。1. 使用社区脚本估算膨胀率PostgreSQL 官方未提供内置膨胀视图但社区有成熟脚本。方法一使用pgstattuple扩展精确但锁表-- 安装扩展CREATEEXTENSION pgstattuple;-- 分析单个索引会加 AccessShareLock短暂阻塞SELECT*FROMpgstatindex(your_index_name);输出关键字段avg_leaf_density叶子页填充率理想 80%leaf_pages实际叶子页数estimated_pages理论所需页数膨胀率 ≈ (leaf_pages - estimated_pages) / leaf_pages。⚠️ 缺点对大索引分析耗时长不适用于高频监控。方法二使用轻量级估算脚本推荐以下 SQL 基于统计信息估算膨胀无锁、快速-- 来源https://github.com/ioguix/pgsql-bloat-estimationWITHbtree_index_attsAS(SELECTnspname,relname,reltuples,relpages,indrelid,relam,regexp_split_to_table(indkey::text, )::smallintASattnum,indexrelidASindex_oidFROMpg_indexJOINpg_classONpg_class.oidpg_index.indexrelidJOINpg_namespaceONpg_namespace.oidpg_class.relnamespaceJOINpg_amONpg_class.relampg_am.oidWHEREpg_am.amnamebtree),index_item_sizesAS(SELECTi.nspname,i.relname,i.reltuples,i.relpages,i.indrelid,i.relam,i.index_oid,SUM(COALESCE(s.stawidth,0))8ASitem_size-- 8 bytes for ctidFROMbtree_index_atts iLEFTJOINpg_stats sONs.schemanamei.nspnameANDs.tablenamei.relnameANDs.attnamepg_get_indexdef(i.indrelid,i.attnum,true)GROUPBYi.nspname,i.relname,i.reltuples,i.relpages,i.indrelid,i.relam,i.index_oid),index_alignedAS(SELECTnspname,relname,reltuples,relpages,indrelid,relam,index_oid,CEIL(reltuples*item_size/(current_setting(block_size)::float-24))ASaligned_est_pagesFROMindex_item_sizes)SELECTnspnameASschema,relnameASindex,indrelid::regclassAStable,relpagesASactual_pages,aligned_est_pagesASestimated_pages,ROUND(100.0*(relpages-aligned_est_pages)/relpages,1)ASbloat_pct,pg_size_pretty((relpages-aligned_est_pages)*current_setting(block_size)::int)ASwasted_spaceFROMindex_alignedWHERErelpages100-- 忽略小索引ANDaligned_est_pages0AND(relpages-aligned_est_pages)100-- 浪费 100 pagesORDERBY(relpages-aligned_est_pages)DESC;bloat_pct 30%且wasted_space 100MB的索引建议重建。五、第四步安全删除无用索引1. 删除前 checklist确认非主键/唯一/外键约束索引确认idx_tup_read 0 AND idx_tup_fetch 0确认近期如 7 天无相关查询结合应用日志在低峰期操作备份 DDL以防误删。2. 执行删除-- 标准删除会锁表阻塞 DMLDROPINDEXCONCURRENTLY your_schema.your_index_name;✅务必使用CONCURRENTLY普通DROP INDEX会加ACCESS EXCLUSIVE锁阻塞所有读写CONCURRENTLY仅加SHARE UPDATE EXCLUSIVE锁允许并发 DML。3. 验证删除效果-- 确认索引消失SELECT*FROMpg_indexesWHEREindexnameyour_index_name;-- 观察磁盘空间释放可能需 VACUUMdu-sh $PGDATA/base/... 注意DROP INDEX立即释放磁盘空间与DELETE不同。六、第五步重建膨胀索引而非删除对于有用但膨胀的索引应重建而非删除。1. 重建命令-- 在线重建PostgreSQL 12REINDEXINDEXCONCURRENTLY your_index_name;-- 旧版本需手动创建切换CREATEINDEXCONCURRENTLY new_indexONtable(col);DROPINDEXCONCURRENTLY old_index;ALTERINDEXnew_indexRENAMETOold_index;2. 自动化重建策略对bloat_pct 50%且wasted_space 1GB的索引自动重建使用 cron 或 pg_cron 定期执行。七、建立自动化监控与治理机制1. 创建监控视图-- 无用索引视图CREATEMATERIALIZEDVIEWunused_indexesASSELECT...-- 上述查询逻辑REFRESH MATERIALIZEDVIEWunused_indexes;-- 每日刷新2. 设置告警Prometheus exporter 采集pg_stat_user_indexes告警规则-alert:UnusedLargeIndexexpr:pg_stat_user_indexes_idx_tup_read 0 and pg_stat_user_indexes_size_bytes1e9for:7dlabels:severity:warning3. 定期巡检脚本Shell psql#!/bin/bash# weekly_index_cleanup.shpsql -Atq -c SELECT DROP INDEX CONCURRENTLY || schemaname || . || indexname || ; FROM pg_stat_user_indexes WHERE idx_tup_read 0 AND idx_tup_fetch 0 AND pg_relation_size(indexrelid) 100*1024*1024 -- 100MB AND indexrelid NOT IN (SELECT conindid FROM pg_constraint); |psql -e⚠️ 脚本需人工审核后再执行八、最佳实践总结场景操作从未使用的非约束索引DROP INDEX CONCURRENTLY低效大索引极少使用评估业务后删除有用但膨胀的索引REINDEX INDEX CONCURRENTLY主键/唯一/外键索引禁止删除即使未用于查询新上线索引监控 7–30 天使用情况无效则清理开发规范建议索引上线需评审提供 EXPLAIN 计划证明必要性命名规范如idx_tab_col1_col2便于识别定期清理每季度执行一次索引健康检查。结语索引是性能的双刃剑——用得好查询飞快用不好拖垮系统。通过本文所述方法你可系统性地识别僵尸索引释放磁盘与内存检测索引膨胀保持高效结构安全删除/重建避免服务中断建立自动化机制实现持续优化。记住最好的索引是刚好够用的索引。定期清理无用索引不仅是节省成本更是对数据库健康负责。

相关新闻

python openai库,深度解析

python openai库,深度解析

1. 它是什么OpenAI 库是一个官方提供的 Python 工具包,它的主要作用是把 OpenAI 提供的各种人工智能服务(例如 GPT、DALLE、Whisper 等)的接口进行了封装,让开发者能用简单的 Python 代码来调用。可以把它想象成一个专门为你跑腿的…

2026/5/17 3:27:31 阅读更多 →
优化校园光环境:从照亮空间到专业护眼照明转变

优化校园光环境:从照亮空间到专业护眼照明转变

近些年以来,伴随社会针对学生视觉健康重视程度的提高之举,教育照明此一细分领域渐渐由单纯的“照亮空间”朝着专业的“光环境塑造”实现转变。研究表明显示,不良的照明环境是致使学生视觉疲劳、注意力降低甚至近视百分比上升的关键因素之一。…

2026/7/6 0:20:56 阅读更多 →
探索风力发电MPPT并网模型:策略模块的奇妙世界

探索风力发电MPPT并网模型:策略模块的奇妙世界

风力发电mppt并网模型,策略模块已mask封装,可以选定步长和变步长2种策略。在风力发电领域,最大功率点跟踪(MPPT)并网模型至关重要,它能让风力发电机尽可能捕获风中的能量,并高效并入电网。今天咱…

2026/7/6 16:15:44 阅读更多 →

最新新闻

2026 合肥 GEO 服务商底层技术架构实测报告|RAG 语义引擎、多模型适配能力横向测评

2026 合肥 GEO 服务商底层技术架构实测报告|RAG 语义引擎、多模型适配能力横向测评

摘要 针对当前合肥 AI 搜索营销赛道服务商技术分层乱象,本文构建一套可复现的 GEO 服务商技术测评指标体系,从RAG 底层自研架构、多模型语义匹配精度、算法迭代响应时延、知识库结构化引擎、数据安全合规架构五大技术维度,对合肥区域主流 GEO…

2026/7/7 9:22:30 阅读更多 →
OBS AI背景移除插件:虚拟绿幕与低光增强的完整实用指南

OBS AI背景移除插件:虚拟绿幕与低光增强的完整实用指南

OBS AI背景移除插件:虚拟绿幕与低光增强的完整实用指南 【免费下载链接】obs-backgroundremoval An OBS plugin for removing background in portrait images (video), making it easy to replace the background when recording or streaming. 项目地址: https:/…

2026/7/7 9:22:30 阅读更多 →
计算机毕业设计之基于大数据的房地产销售数据分析系统

计算机毕业设计之基于大数据的房地产销售数据分析系统

随着房地产市场的日益繁荣,大数据技术在房地产销售领域的应用越来越广泛。本文旨在探讨基于大数据的房地产销售数据分析系统的设计与实现。通过收集和整合大量的房地产销售数据,利用大数据分析技术对其进行深入挖掘,为房地产企业和购房者提供…

2026/7/7 9:20:29 阅读更多 →
UE4SS在Palworld 0.1.3.0版本中的崩溃诊断与兼容性修复方案

UE4SS在Palworld 0.1.3.0版本中的崩溃诊断与兼容性修复方案

UE4SS在Palworld 0.1.3.0版本中的崩溃诊断与兼容性修复方案 【免费下载链接】RE-UE4SS Injectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games 项目地址: https://gitcode.com/gh_mirrors/re/RE-UE4SS 技…

2026/7/7 9:20:29 阅读更多 →
Obsidian:从云端焦虑到知识自由之路

Obsidian:从云端焦虑到知识自由之路

作为一个常年与文档打交道的IT人,我最早用的是语雀和有道笔记等。这些产品功能确实强大,但有两个痛点让我越来越焦虑: 收费越来越贵:语雀个人版免费额度有限,想用Markdown、图床等功能就得付费;有道笔记的…

2026/7/7 9:16:29 阅读更多 →
Livox Horizon 多激光雷达外参自动标定:基于点云特征匹配的 3 步实战流程

Livox Horizon 多激光雷达外参自动标定:基于点云特征匹配的 3 步实战流程

Livox Horizon 多激光雷达外参自动标定:基于点云特征匹配的3步实战流程在自动驾驶系统的开发中,多激光雷达的协同工作能力直接决定了环境感知的精度和可靠性。Livox Horizon作为一款高性能固态激光雷达,其独特的非重复扫描模式为点云质量带来…

2026/7/7 9:16:28 阅读更多 →

日新闻

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

图片浏览是移动应用中最高频的场景之一。从社交应用的照片流到电商平台的商品图集,从旅游应用的景点相册到摄影作品展示——用户对图片浏览的体验要求不断提高:流畅的切换动画、直观的缩略图导航、便捷的收藏操作、自动播放模式。HarmonyOS NEXT ArkUI 虽…

2026/7/7 0:05:16 阅读更多 →
24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V稳压芯片完整选型指南 PW8600 PW75XX PW2815 PW2312B LDODC/DC全方案 一、24V稳压方案概述 24V直流电源在工业自动化、门禁系统、电梯控制、汽车电子、LED驱动、监控设备等场景中应用极广,是最常见的中压直流母线电压。要将24V母线稳定降压至下游MCU、传感器…

2026/7/7 0:05:16 阅读更多 →
RAG+知识图谱混合检索与Graph RAG核心对比

RAG+知识图谱混合检索与Graph RAG核心对比

做企业RAG落地的团队,往往容易卡在一容易踩坑的选型难题: 当需求单纯靠向量RAG搞不定、单纯靠知识图谱也搞不定,必须同时依赖「文本语义理解 实体关系推理」时,到底是做「向量图谱混合检索」就够了,还是必须上「Grap…

2026/7/7 0:07:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻