环境:
1)redhat-release:CentOS Linux release 7.6.1810 (Core)
2)database version:postgresql 14.6
一、添加pgstattuple
pgcompacttable工具使用过程中需要依赖pgstattuple,因此需先添加pgstattuple。如果是源码安装的postgresql,则源码里包含了postgresql-contrib,因此,进行编译及安装即可。
--编译
cd /postgresql/soft/postgresql-14.6/contrib/pgstattuple
make
make install
本次实验没有编译也可以直接使用。
--在所需要使用的数据库里添加pgstattuple。
[postgres@tencent ~]$ psql -d testdb -Utest
psql (14.6)
Type "help" for help.
testdb=# select * from pg_available_extensions where name like 'pgstat%';
name | default_version | installed_version | comment
-------------+--------------+---------------+--------------------
pgstattuple | 1.5 | | show tuple-level statistics
(1 row)
testdb=#create extension pgstattuple;
CREATE EXTENSION
testdb=# select * from pg_available_extensions where name like 'pgstat%';
name | default_version | installed_version | comment
-------------+-----------------+-------------------+-----------------------------
pgstattuple | 1.5 | 1.5 | show tuple-level statistics
(1 row)
安装完成后,installed_version显示安装的版本
--查看pgstattuple可使用的函数
testdb=# \dxS+ pgstattuple
Objects in extension "pgstattuple"
Object description
---------------------------------------
function pg_relpages(regclass)
function pg_relpages(text)
function pgstatginindex(regclass)
function pgstathashindex(regclass)
function pgstatindex(regclass)
function pgstatindex(text)
function pgstattuple_approx(regclass)
function pgstattuple(regclass)
function pgstattuple(text)
(9 rows)
二、部署pgcompacttable
安装前需要安装pgstattuple插件,因为要基于该插件去查找膨胀的表,所以如果有大表的情况下,因为pgstattuple会扫全表,所以会比较耗时,这个在使用的时候一定要注意一下。
原理:
从表的头部填充新的行,在普通vacuum时候,截断表末尾的空page,达到收缩空间的效果。不需要占用额外的空间,使得表文件更加紧凑。而且不会加比较重的锁。对性能影响较小。
--安装依赖包
[root@tencent ~]# yum install perl-Time-HiRes perl-DBI perl-DBD-Pg –y
--上传解压安装包
上传pgcompacttable-master.zip 到/postgresql/soft目录,unzippgcompacttable-master.zip
--查看文件
[postgres@tencent soft]$ cd pgcompacttable-master/
[postgres@tencent pgcompacttable-master]$ ls
bin README.md
[postgres@tencent pgcompacttable-master]$ cd bin
[postgres@tencent bin]$ ls
Pgcompacttable
三、准备测试环境
3.1 创建表
--创建表
testdb=#create table test (id in,sex char(2),name varchar(10),now_address text,address text);
--插入数据
testdb=# insert into test values(generate_series(1,10000),repeat(chr(int4(random()*26)+65),1),repeat(chr(int4(random()*26)+65),6),repeat(chr(int4(random()*26)+65),30),repeat(chr(int4(random()*26)+65),30));
INSERT 0 10000
--创建索引
testdb=# create index on test(id,sex);
CREATE INDEX
testdb=# create index on test(name,now_address,address);
CREATE INDEX
--查看表大小
testdb=# select pg_size_pretty(pg_relation_size('test'));
pg_size_pretty
----------------
1072 kB
(1 row)
testdb=# select count(*) from test;
count
-------
10000
(1 row)
3.2 模拟修改数据
创建脚本:
[postgres@tencent scripts]$ vi test_mod.sh
#!/bin/bash
#version: 1.0
#function: bulk update data
for((i=1;i<=10000;i++));
do
a=`tr -dc A-Z[ < /dev/urandom | head -c1`
psql -Utest -h 127.0.0.1 -d testdb -c "update test set name=repeat( chr(int4(random()*26)+65),6),now_address=repeat( chr(int4(random()*26)+65),30),address=repeat( chr(int4(random()*26)+65),30) where sex='$a';" >>/dev/null
if [ $? == 0 ]
then
echo "$a is ok" >>update.log
else
echo "$a is close" >>update.err.log
exit 1;
fi
done
3.3 膨胀再现
为了执行脚本不输入密码,创建了.pgpass文件
--查看postgres家目录
[postgres@tencent bin]$ grep postgres /etc/passwd
postgres:x:601:601::/home/postgres:/bin/bash
--创建.pgpass
touch /home/postgres/.pgpass
chown postgres. /home/postgres/.pgpass
chmod 600 /home/postgres/.pgpass
--配置.pgpass
[postgres@tencent ~]$ echo "127.0.0.1:4519:testdb:test:test" >>./.pgpass
--连接测试
[postgres@tencent ~]$ psql -h 127.0.0.1 -d testdb -Utest
psql (14.6)
Type "help" for help.
testdb=#
连接成功。
--执行批量修改脚本
[postgres@tencent scripts]$ sh test_mod.sh
--查看元组的统计信息
testdb=# SELECT * FROM pgstattuple('test');
table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent
--------+-------+------+-------+------+------+------+-------+---
27795456 | 10258 | 1025800 | 3.69 | 19617 | 1961700 | 7.06 | 24071216 | 86.6
(1 row)
pgstattuple 输出列如下:
字段 类型 描述
table_len bigint 物理关系长度,以字节计
tuple_count bigint 活的元组的数量
tuple_len bigint 活的元组的总长度,以字节计
tuple_percent float8 活的元组的百分比
dead_tuple_count bigint 死的元组的数量
dead_tuple_len bigint 死的元组的总长度,以字节计
dead_tuple_percent float8 死的元组的百分比
free_space bigint 空闲空间总量,以字节计
free_percent float8 空闲空间的百分比
--查看表的大小
testdb=# select pg_size_pretty(pg_relation_size('test'));
pg_size_pretty
----------------
27 MB
(1 row)
存1w条数据原表大小1096 KB,目前27MB
四、pgcompacttable使用
pgcompacttable可以对database级别、schema级别、table级别进行压缩
./pgcompacttable -h localhost -U postgres -d testdb
./pgcompacttable -h localhost -U postgres -d testdb -n test
./pgcompacttable -h localhost -U postgres -d testdb -n test -t test
[postgres@tencent bin]$ ./pgcompacttable -h 127.0.0.1 -U test -d testdb
--查看压缩后的表
testdb=# SELECT * FROM pgstattuple('test');
table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent
-----------+----------+-----------+---------+---------+----------+----------+--------+-------
1114112 | 10000 | 1000000 | 89.76 | 0 | 0 | 0 | 12456 | 1.12
(1 row)
testdb=# select pg_size_pretty(pg_relation_size('test'));
pg_size_pretty
----------------
1088 kB
(1 row)
恢复至源表大小。