一、数据碎片

一般来讲,PG/GP表中的数据在删除后会被标记为dead,除非进行自动的autovacuum(据数Greenplum禁用了autovacuum)或者是手动的vacuum,否则数据块不会被回收,直观的看来就是表的体积大,操作系统里表的文件臃肿不减。

问题描述可参考:https://my.oschina.net/courtzjl/blog/1602713

二、碎片查询

通过查询pg_stat_user_tables,可以基本清除哪些表的全表扫描次数较多,表中DML哪种操作多,也可以了解垃圾数据的数量。该表的各个字段描述如下:

--------------------+------------------------------
relid               | 16440        #表oid
schemaname          | public       #模式名
relname             | t1           #表名
seq_scan            | 50           #这个表进行全表扫描的次数
seq_tup_read        | 1867763      #全表扫描的数据行数,如果这个值很大说明操作这个表的SQL语句很可能是全表扫描,需要结合执行计划分析
idx_scan            |              #索引扫描的次数
idx_tup_fetch       |              #通过索引扫描返回的行数
n_tup_ins           | 1130502      #插入的数据行数
n_tup_upd           | 0            #更新的数据行数
n_tup_del           | 81920        #删除的数据行数
n_tup_hot_upd       | 0            #hot update的数据行数,这个值与n_tup_upd接近说明更新性能较好,不需要更新索引
n_live_tup          | 655366       #活的行数量
n_dead_tup          | 0            #死记录个数
n_mod_since_analyze | 6            #上次analyze的实际
last_vacuum         | 2019-04-07 00:22:00.955542-07 #上次手动vacuum的实际
last_autovacuum     |              #上次autovacuum的实际
last_analyze        |              #上次analyze时间
last_autoanalyze    | 2019-04-07 00:26:07.668391-07 #上次自动analyze时间
vacuum_count        | 2            #vacuum次数
autovacuum_count    | 0            #自动vacuum次数
analyze_count       | 0            #analyze次数
autoanalyze_count   | 10           #自动analyze次数
--------------------+------------------------------

注:参考文章:http://blog.itpub.net/31493717/viewspace-2643152/

其中字段n_dead_tup记录了垃圾数据的数量,可通过n_dead_tup>0筛选出还有垃圾数据的表,即SQL如下:

select relname,n_dead_tup from pg_stat_user_tables where n_dead_tup>0;

当查到表后,可使用:

select pg_size_pretty(pg_relation_size('t_test_table'));

查看到表所占用的物理空间的大小。

三、垃圾回收

当找到存在碎片垃圾数据的表后,可使用vacuum进行垃圾回收,它的作用是删除那些已经标示为删除的数据并释放空间。

1、碎片垃圾产生原因

(1)Greenplum底层的PostgreSQL中已经 DELETE 的元组或者被 UPDATE 过后过时的元组是没有从它们所属的表中物理删除的;

(2)数据库的每个事务对应着一个ID,当ID个数超过数据库限定的阈值时,就会重复用前面的ID,造成混乱。每个数据库每2百万个事务的时候,对每张表执行VACUUM是很有必要的

(3)大量的CREATE和DROP命令会导致系统表的迅速膨胀,以至于影响系统性能。

(4)过期的记录会被存放在叫做自由空间映射的地方;超出自由空间映射空间的过期记录所占用的空间无法回收;VACUUM FULL命令将回收所有过期记录,但是耗时长;使用CREATE TABLE AS来处理自由空间溢出的情况,例如t_table01自由空间溢出:

create table "t_table02" as select from "t_table01",drop table "t_table01";

2、使用vacuum

VACUUM 回收已删除元组占据的存储空间。在完成VACUUM 之前它们仍然存在。 因此我们有必须周期地运行 VACUUM, 特别是在常更新的表上。

重要:PostgreSQL有一个单独的可选服务器进程,称为autovacuum daemon,其目的是自动执行VACUUM和ANALYZE命令。 Greenplum数据库开启autovacuum守护程序仅在Greenplum数据库模板数据库template0上执行VACUUM操作。 为template0启用了autovacuum,因为不允许连接到template0。 autovacuum守护程序在template0上执行VACUUM操作以管理事务ID(XID),并帮助避免template0中的事务ID环绕问题。

文档地址:http://docs-cn.greenplum.org/v6/ref_guide/sql_commands/VACUUM.html

语法格式:

VACUUM [({ FULL | FREEZE | VERBOSE | ANALYZE } [, ...])] [table [(column [, ...] )]]
        
VACUUM [FULL] [FREEZE] [VERBOSE] [table]

VACUUM [FULL] [FREEZE] [VERBOSE] ANALYZE
              [table [(column [, ...] )]]

参数

  • FULL
    选择full vacuum,这可以回收更多空间,但是需要更长的时间排他锁定表。 此方法还需要额外的磁盘空间,因为它会写入表的新副本,并且在操作完成之前不会释放旧副本。 通常,仅在需要从表中回收大量空间时才应使用此选项。

  • FREEZE
    指定FREEZE等效于将vacuum_freeze_min_age服务器配置参数设置为零来执行VACUUM。 请参阅服务器配置参数以获取有关vacuum_freeze_min_age的信息。

  • VERBOSE
    为每个表打印详细的vacuum活动报告。

  • ANALYZE
    更新优化器使用的统计信息,以确定执行查询的最快方法。

  • table
    要vacuum的表的名称(可以用schema修饰)。 默认为当前数据库中的所有表。

  • column
    要分析的特定列的名称。 默认为所有列。 如果指定了列列表,则意味着ANALYZE。

四、参考与推荐文章:

  • https://blog.csdn.net/xfg0218/article/details/83031550
  • https://www.cnblogs.com/orangeform/archive/2012/05/23/2304155.html
  • https://github.com/digoal/blog/blob/master/201708/20170817_01.md
  • http://blog.chinaunix.net/uid-20726500-id-4864672.html
  • https://www.cnblogs.com/orangeform/archive/2012/05/23/2304155.html

本文地址:https://blog.csdn.net/inrgihc/article/details/110958571