pg 定期vacuum和reindex

本文涉及的产品
PolarDB Agent Express,2核4GB
云数据库 PolarDB MySQL 版,列存表分析加速 4核8GB
简介:
定期vacuum和reindex: 
一、说明 

    postgresql数据库执行delete操作后,表中的记录只是被标示为删除状态,并没有释放空间,在以后的update或insert操作中该部分的空间是不能够被重用的。在postgresql中用于维护数据库磁盘空间的工具是VACUUM,其作用是删除那些已经标示为删除的数据并释放空间。但vacuum工具不能够对相应的索引进行清理,需要手动去重建索引。 

   因此日常我们需要定期的做一些vacuum和reindex的操作。 

二、vacuum 

VACUUM语法结构: 
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ table ] 
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ] 

1)vacuum 、vacuum full、vacuum analyze、autovacuum 命令的区别 
vacuum          只是将删除状态的空间释放掉,转换到能够重新使用的状态,但是它不进行空间合并。 
vacuum full     将会使空间释放的信息表现在系统级别,其实质是将当前删除记录后面的数据进行移动,使得整体的记录连贯 
                起来,降低了“高水位标记”。因此它需要lock table。 
vacuum analyze  更新统计信息,使得优化器能够选择更好的方案执行sql。 
autovacuum      数据库定时自动进行vacuum 


备注: 
1、对于有大量update 的表,vacuum full是没有必要的,因为它的空间还会再次增长,所以vacuum就足够了。 
2、oracle中同样也有analyze,作用也相同,目前更多的使用的是dbms_stats包。统计信息收集和更新对于系统性能来说非常重要。 
   oracle在进行imp后自动的对相应数据对象进行统计信息的收集和更新,而postgresql的恢复过程还没有集成到里面,需要手动去执行。 
3、适当调大参数maintenance_work_mem,可加快vacuum的执行速度 

举例: 
tina=# vacuum t_sfa_sample;    ---非常快速(10s内)就执行完了 
VACUUM 
tina=# vacuum full t_sfa_sample;  ---约几分钟(表越大,时间越长) 
VACUUM 
tina=# vacuum analyze t_sfa_sample;  
VACUUM 

2)autovacuum参数配置 
执行直接由autovacuum参数值决定,默认值是on。但当需要冻结xid时,即使此值为off,PG也会进行vacuum: 

log_autovacuum_min_duration:默认值为-1,关闭vacuum的日志记录,配置为0表示记录autovacuum的所有log。参数设置为正整数表示对于在此时间内完成的vacuum操作不进行log记录,如果没能完成,则记录超出时间内的log 

autovacuum_max_workers:最大的autovacuum进程的数量,默认值为3。参数大小的配置主要依据系统当前负载和资源。对于系统负载较重的情况,建议开启少量的进程为好,反之,空闲时间可以采用较大值的方式 

autovacuum_naptime:检查数据库的时间间隔。默认为1分钟。这个naptime会被vacuum launcher分配到每个DB上,autovacuum_naptime/num of db。 

autovacuum_vacuum_threshold:参数表示执行autovacuum操作之前,对单个表中记录执行DML操作的最少行数。达到该行数时自动激活autovacuum操作。该参数针对数据库中的所有表,还可以通过对单个表配置不同的值来改变相应表的autovacuum操作。默认值是50。与autovacuum_vacuum_scale_factor配合使用,当update,delete的tuples数量超过autovacuum_vacuum_scale_factor*table_size+autovacuum_vacuum_threshold时,进行vacuum。如果要使vacuum工作勤奋点,则将此值改小。 
                             
autovacuum_analyze_threshold:激活自动analyze操作的最小行数。默认值50。与autovacuum_analyze_scale_factor配合使用,当update,insert,delete的tuples数量超过autovacuum_analyze_scale_factor*table_size+autovacuum_analyze_threshold时,进行analyze 

autovacuum_vacuum_scale_factor:该参数采用百分比的方式设定阀值。默认值为20%,当DML涉及的数据量大于某个表的20%时,自动触发autovacuum操作。同样可以通过对单个表进行阀值设定 

autovacuum_analyze_scale_factor:机制与上面相同,到达阀值是自动激活analyze操作。同样可以通过对单个表进行阀值设定 

autovacuum_freeze_max_age:为防止事务ID的重置,在启用vacuum操作之前,表的pg_class .relfrozenxid字段的最大值,默认为200万 

autovacuum_vacuum_cost_delay:autovacuum进程的时间延迟限制,默认值是20ms。对于单个表同样适用。取vacuum_cost_delay值 

autovacuum_vacuum_cost_limit:autovacuum进程的开销延迟限制,默认值是-1,表示不进行开销限制,到vacuum_cost_limit的值,这个值是所有worker的累加值。 


基于代价的vacuum参数: 
vacuum_cost_delay :计算每个毫秒级别所允许消耗的最大IO,vacuum_cost_limit/vacuum_cost_dely。 默认vacuum_cost_delay为20毫秒。 
vacuum_cost_page_hit :vacuum时,page在buffer中命中时,所花的代价。默认值为1。 
vacuum_cost_page_miss:vacuum时,page不在buffer中,需要从磁盘中读入时的代价默认为10。 
vacuum_cost_page_dirty:当vacuum时,修改了clean的page。这说明需要额外的IO去刷脏块到磁盘。默认值为20。 
vacuum_cost_limit:当超过此值时,vacuum会sleep。默认值为200。 

备注:在某些情况下,最好是把autovacuum关掉,因为postgresql.conf中,你看到autovacuum前面加了#号,但其实是默认设置为开启。而且这个vacuum是对所有的数据库进行vacuum,如果有那么一个数据库中表多数据大,ddl操作也多,那就导致cpu超高,而且持续时间特长。我们可以设置autovacuum=off ,然后对经常使用的database进行脚本vacuum,设定自动的时间最好是数据库使用不多的时间段,比如半夜。 
在进行vacuum时,耗资源耗内存,有时候还会锁死。 

例如脚本: 
cat pg_engine_vacuum.sh 
#!/bin/bash 
#2014-10-22 tina 
date=`date +"%Y-%m-%d %H:%M:%S"` 
echo "begin time is: $date" >>/tmp/pg_tinadb_vacuum.log 

tables=$(psql -U postgres -d tinadb -c "select tablename from pg_tables where schemaname='public';" |grep -v "tablename") 
echo $tables >>/tmp/pg_tinadb_vacuum.log 

for table in $tables 
do 
psql -U postgres -d tinadb -c "vacuum full $table;" >>/tmp/pg_tinadb_vacuum.log 
echo "table $table has finished vacuum.">>/tmp/pg_tinadb_vacuum.log 
done 

添加到crontab 定时执行即可。 


3)命令设置某个表不进行autovacuum: 
tina=# alter table test1 set (autovacuum_enabled=false); 
ALTER TABLE 
tina=# select relname from pg_class where reloptions@>array['autovacuum_enabled=false']; 
relname 
--------- 
test1 
(1 row) 

三、reindex 
reindex命令: 
REINDEX { INDEX | TABLE | DATABASE | SYSTEM } name [ FORCE ] 

REINDEX 使用存储在索引的表上的数据重建索引, 替换旧的索引拷贝。使用 REINDEX 有两个主要原因: 
1、索引崩溃,并且不再包含有效的数据。尽管理论上这是不可能发生的, 但实际上索引会因为软件毛病或者硬件问题而崩溃。 
2、要处理的索引包含大量无用的索引页未被回收。在某些情况下, 这个问题会发生在 PostgreSQL 里面的B-树索引上。 
   
   对于B-Tree索引,只有那些已经完全清空的索引页才会得到重复使用,对于那些仅部分空间可用的索引页将不会得到重用,如果一个页面中大多数索引键值都被删除,只留下很少的一部分,那么该页将不会被释放并重用。在这种极端的情况下,由于每个索引页面的利用率极低,一旦数据量显著增加,将会导致索引文件变得极为庞大,不仅降低了查询效率,而且还存在整个磁盘空间被完全填满的危险。对于重建后的索引还存在另外一个性能上的优势,因为在新建立的索引上,逻辑上相互连接的页面在物理上往往也是连在一起的,这样可以提高磁盘页面被连续读取的几率,从而提高整个操作的IO效率。 

postgres=# reindex database tina; 
ERROR:  can only reindex the currently open database 
postgres=# \c tina 
You are now connected to database "tina" as user "postgres". 
tina=# reindex database tina; 
NOTICE:  table "pg_catalog.pg_class" was reindexed 
NOTICE:  table "pg_catalog.pg_statistic" was reindexed 
.... 
会将当前open的tina库里的索引都重建 

reindx table tablename; 
会将表中的所有索引都重建 

reindex index indexname; 
会将指定的这一个索引重建 

索引原大小:    
SELECT relname, pg_relation_size(oid)/1024 || 'K' AS size FROM pg_class WHERE relkind='i' and relname='t_cert_sample_state_idx'; 
         relname         |  size   
-------------------------+--------- 
t_cert_sample_state_idx | 106000K 
(1 row) 


重建索引: 
REINDEX INDEX t_cert_sample_state_idx; 
REINDEX 

重建后索引大小: 
SELECT relname, pg_relation_size(oid)/1024 || 'K' AS size FROM pg_class WHERE relkind='i' and relname='t_cert_sample_state_idx'; 
         relname         |  size  
-------------------------+-------- 
t_cert_sample_state_idx | 94648K 
(1 row) 

索引重建后一定要分析表: 
ANALYZE t_cert; 
ANALYZE 


补充: 
1. 查看表所占用的磁盘页面数  
SELECT relfilenode, relpages FROM pg_class WHERE relname = 't_cert'; 
relfilenode | relpages 
-------------+---------- 
    49037978 |   384895 
(1 row) 
说明:relpages只能被VACUUM、ANALYZE和几个DDL命令更新,如CREATE INDEX。通常一个页面的长度为8K字节。 
   
    
2. 查看表的索引名和索引占用的磁盘页面数量。 
SELECT c2.relname, c2.relpages FROM pg_class c, pg_class c2, pg_index i 
WHERE c.relname = 't_cert' AND c.oid = i.indrelid AND c2.oid = i.indexrelid ORDER BY c2.relname; 
             relname              | relpages 
----------------------------------+---------- 
sign_android_pkey                |    11659 
t_cert_sample_state_idx          |    11831 
t_cert_serialnumber_hash_md5_key |    45887 
(3 rows) 

3.查看表大小    
SELECT pg_relation_size('t_cert')/1024/1024 || 'MB' AS size; 
  size  
-------- 
3007MB 
(1 row) 

4.查看索引大小 
SELECT pg_relation_size('t_cert_sample_state_idx')/1024/1024 || 'MB' AS size; 
size 
------ 
92MB 
(1 row)
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
网络协议 安全 网络安全
自定义QTableView右键弹出菜单, 并复制选中的单元格内容到剪贴板中
自定义QTableView右键弹出菜单, 并复制选中的单元格内容到剪贴板中
1225 0
|
SQL 关系型数据库 分布式数据库
PostgreSQL 在线修改数据类型 - online ddl 方法之一
标签 PostgreSQL , online ddl , trigger , ddl 事务 背景 有张表的主键id是serial,但现在不够了,需要升级成bigserial,有什么优雅的方法吗?我看下来好像会锁表很久(因为数据量挺大) 如果直接alter table,由于数据类型从4字节改成了8字节,而tuple结构是在METADATA里面的,不是每行都有,所以DEFORM需要依赖METADATA,目前来说,这种操作需要rewrite table。
4947 0
|
9月前
|
人工智能 运维 Cloud Native
阿里云Serverless计算产品入选Gartner®报告「领导者」象限!
近日,Gartner® 发布了 2025 年度全球《云原生应用平台魔力象限》报告,阿里云凭借 Serverless 应用引擎 SAE(以下简称 SAE)和函数计算 FC,成为亚太地区唯一入选「领导者象限」的科技公司。
794 18
|
11月前
|
存储 监控 关系型数据库
B-tree不是万能药:PostgreSQL索引失效的7种高频场景与破解方案
在PostgreSQL优化实践中,B-tree索引虽承担了80%以上的查询加速任务,但因多种原因可能导致索引失效,引发性能骤降。本文深入剖析7种高频失效场景,包括隐式类型转换、函数包裹列、前导通配符等,并通过实战案例揭示问题本质,提供生产验证的解决方案。同时,总结索引使用决策矩阵与关键原则,助你让索引真正发挥作用。
715 0
|
SQL 关系型数据库 数据库
PostgreSQL性能飙升的秘密:这几个调优技巧让你的数据库查询速度翻倍!
【10月更文挑战第25天】本文介绍了几种有效提升 PostgreSQL 数据库查询效率的方法,包括索引优化、查询优化、配置优化和硬件优化。通过合理设计索引、编写高效 SQL 查询、调整配置参数和选择合适硬件,可以显著提高数据库性能。
2679 2
|
运维 监控 关系型数据库
运维实战:Windows服务挂掉了怎么办,通过Bat脚本实现自动重启
本文介绍了如何使用Bat脚本自动监控并重启Windows服务器上的挂掉服务,例如MySQL,以避免在假期等情况下需要紧急处理问题。首先,创建一个Bat脚本,设定每小时检查一次服务状态,如果服务停止则自动重启。脚本内容包括检查服务是否运行并根据状态执行相应操作。同时,脚本中包含了确保以管理员权限运行的代码。 脚本需设置为ANSI编码以防止乱码。推荐将Bat脚本封装为Windows服务以保证稳定运行,提供了使用NSSM工具、Windows服务程序和开源的Java工具winsw将批处理脚本转化为服务的方法。这些方法可以确保服务在后台可靠运行,即使在服务意外停止时也能自动恢复。
【OpenGL】十二、OpenGL 绘制线段 ( 绘制单条线段 | 绘制多条线段 | 依次连接的点组成的线 | 绘制圈 | 绘制彩色的线 )(一)
【OpenGL】十二、OpenGL 绘制线段 ( 绘制单条线段 | 绘制多条线段 | 依次连接的点组成的线 | 绘制圈 | 绘制彩色的线 )(一)
534 0
【OpenGL】十二、OpenGL 绘制线段 ( 绘制单条线段 | 绘制多条线段 | 依次连接的点组成的线 | 绘制圈 | 绘制彩色的线 )(一)
|
关系型数据库 MySQL Java
实时计算 Flink版操作报错合集之遇到删除操作时,出现Failed to deserialize data of EventHeaderV4 错误如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
635 5
|
存储 SQL 缓存
一文带你了解MySQL之InnoDB_Buffer_Pool
通过前边的学习我们知道,对于使用InnoDB作为存储引擎的表来说,不管是用于存储用户数据的索引(包括聚簇索引和二级索引),还是各种系统数据,都是以页的形式存放在表空间中的,而所谓的表空间只不过是InnoDB对文件系统上一个或几个实际文件的抽象,也就是说我们的数据说到底还是存储在磁盘上的。但是各位也都知道,磁盘的速度慢的跟乌龟一样,怎么能配得上“快如风,疾如电”的CPU呢?所以InnoDB存储引擎在处理客户端的请求时,当需要访问某个页的数据时,就会把完整的页的数据全部加载到内存中,也就是说即使我们只需要访问一个页的一条记录,那也需要先把整个页的数据加载到内存中。
5221 2

热门文章

最新文章