Gp在测试环境,运行了一段时间,发现一个很蹊跷的问题,每天增量入库的速度,越来越慢,检查了一个记录是0的tmp表,发现居然占用了32gb的空间!

满世界找资料,发现了症结所在,原来postgresql的delete动作,并不是真正物理删除,而是只在被删除的记录上做了个标记,只有执行vacuum操作后,才能真正的删除,当前设置 show autovacuum = off。

下面是同一个tmp表,执行vacuum前后占用的空间:

h2000=# VACUUM ANALYZE xxxxxx;

VACUUM

h2000=# select pg_relation_size(xxxxxx);

 pg_relation_size

------------------

       8788279296

(1 row)

 

h2000=# VACUUM FULL xxxxxx;

VACUUM

 

h2000=# select pg_relation_size(xxxxxx);

 pg_relation_size

------------------

         46596096

 

执行vacuum不但占用空间少了很多,而且,针对该表执行的数据操作,快了n倍,Vacuum常用的参数为:空、analyze、full,作用各有不同,根据实际测试,每天运行一下vacuum analyze对于性能的提升是非常有效的,现在困惑与full,根据帮助文件和测试结果,进行full操作,是可以释放出更多硬盘资源的,并且性能提升的程度也更好一些,但是进行full操作是,系统提示非安全,并且会在该表加一个排他锁,速度也慢很多,计划周末晚上,试一下full,看看效果。

Full Vacuum
full vacuum与单纯的vacuum还是有很大的区别的。vacuum只是将删除状态的空间释放掉,转换到能够重新使用的状态,但是对于系统来说该数据块的 空闲空间并没有反应到系统的元数据中。类似oracle中高水位标记并没有下降。Full vacuum将会使空间释放的信息表现在系统级别,其实质是将当前删除记录后面的数据进行移动,使得整体的记录连贯起来,降低了“高水位标记”。
Vacuum analyze
analyze 的功能是更新统计信息,使得优化器能够选择更好的方案执行sql。oracle中同样也有analyze,作用也相同,目前更多的使用的是 dbms_stats包。统计信息收集和更新对于系统性能来说非常重要,与oracle维护类似,通常可以通过采用手动或者定制任务的方式。也有不 同,oracle在进行imp后自动的对相应数据对象进行统计信息的收集和更新,而postgresql的恢复过程还没有集成到里面,需要手动去执行。

Postgresql还提供了一种自动运行vacuum的方式,不过鉴于目前以提升查询效率优先,且增量入库采用tmp中转一次,且这种方式比较不可控,故不用。

附录:

VACUUM

Name

VACUUM -- 垃圾收集以及可选地分析一个数据库

Synopsis

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

描述

VACUUM 回收已删除元组占据的存储空间。 在一般的 PostgreSQL 操作里, 那些已经 DELETE 的元组或者被 UPDATE 过后过时的元组是没有从它们所属的表中物理删除的; 在完成 VACUUM 之前它们仍然存在。 因此我们有必须周期地运行 VACUUM, 特别是在常更新的表上。

如果没有参数,VACUUM 处理当前数据库里每个表, 如果有参数,VACUUM 只处理那个表。

VACUUM ANALYZE 先执行一个 VACUUM 然后是给每个选定的表执行一个 ANALYZE。 对于日常维护脚本而言,这是一个很方便的组合。参阅 ANALYZE 获取更多有关其处理的细节。

简单的 VACUUM (没有FULL) 只是简单地回收空间并且令其可以再次使用。这种形式的命令可以和对表的普通读写并行操作, 因为没有请求排他锁。VACUUM FULL 执行更广泛的处理,包括跨块移动元组,以便把表压缩到最少的磁盘块数目里。 这种形式要慢许多并且在处理的时候需要在表上施加一个排它锁。

FREEZE 是一种特殊用途的选项,它导致元组尽可能快地标记为"冻结(frozen)", 而不是等到它们已经相当老的时候才标记。如果在同一个数据库上没有其它运行着的事务的时候完成这个命令, 那么系统就保证在数据库里的所有元组都是"冻结(frozen)"的, 因此不会有事务 ID 重叠的问题,而和数据库未清理的时间没有关系。 我们不建议把 FREEZE 用做日常用途。我们用它的唯一目的是准备和用户定义的模板数据库联接的时候, 或者是其它完全是只读的, 不会等到日常维护性 VACUUM 操作的数据库。 参阅 Chapter 22 获取细节。

参数

FULL

选择"完全"清理,这样可以恢复更多的空间, 但是花的时间更多并且在表上施加了排它锁。

FREEZE

选择激进的元组"冻结"

VERBOSE

为每个表打印一份详细的清理工作报告。

ANALYZE

更新用于优化器的统计信息,以决定执行查询的最有效方法。

table

要清理的表的名称(可以有模式修饰)。缺省时是当前数据库中的所有表。

column

要分析的具体的列/字段名称。缺省是所有列/字段。

输出

如果声明了 VERBOSEVACUUM 发出过程信息, 以表明当前正在处理那个表。各种有关这些表的统计也会打印出来。

注意

我们建议在经常VACUUMM(清理)(至少每晚一次)生产数据库, 以保证不断地删除失效的行。尤其是在增删了大量记录之后, 对受影响的表执行 VACUUM ANALYZE 命令是一个很好的习惯。这样做将更新系统目录为最近的更改,并且允许 PostgreSQL 查询优化器在规划用户查询时有更好的选择。

我们不建议日常使用 FULL 选项,但是可以在特殊情况下使用。 一个例子就是在你删除了一个表的大部分行之后,希望从物理上缩小该表以减少磁盘空间占用。VACUUM FULL 通常要比单纯的 VACUUM 收缩更多表的尺寸。

VACUUM 导致 I/O 流量的潜在地增加, 可能会导致其它活动的绘画的性能恶劣。因此,有时候我们会建议使用基于开销的 vacuum 延迟特性。 参阅 Section 17.4.4 获取细节。

 

17.9. 自动清理

这些设置控制自动清理守护进程的缺省行为。 请参阅 Section 22.1.4 获取更多信息。

autovacuum (boolean)

控制服务器是否应该启动 autovacuum 子进程。 缺省的时候这个是关闭的。 要想启动这个进程, stats_start_collectorstats_row_level 也必须是打开的。 这个选项只能在服务器启动的时候设置, 或者在文件 postgresql.conf 里设置。

autovacuum_naptime (integer)

声明 autovacuum 子进程的活跃期之间的延迟。 在每次运行的周期里,子进程都会检查一个数据库,并根据需要为该数据库的表发出 VACUUMANALYZE 命令。 这个延迟是以秒计的,缺省为 60。 这个选项只能在服务器启动的时候或者是在文件 postgresql.conf 里设置。

autovacuum_vacuum_threshold (integer)

声明在任何表里触发 VACUUM 所需要的最小的元组的更新或者删除的数量。 缺省是 1000。 这个选项只能在服务器启动的时候或者是在文件 postgresql.conf 里设置。

autovacuum_analyze_threshold (integer)

声明在任何表里触发 ANALYZE 所需要的最小的元组的插入,更新或者删除的数量。 缺省是 500。 这个选项只能在服务器启动的时候或者是在文件 postgresql.conf 里设置。 这个设置可以被 pg_autovacuum 表里面的为每个表的独立条目覆盖。

autovacuum_vacuum_scale_factor (floating point)

声明在判断是否触发一个 VACUUM 时增加到 autovacuum_vacuum_threshold 参数里面的表的尺寸之比例。缺省是 0.4。 这个选项只能在服务器启动的时候或者是在文件 postgresql.conf 里设置。 这个设置可以被 pg_autovacuum 表里面为每个表的独立条目覆盖。

autovacuum_analyze_scale_factor (floating point)

声明在判断是否触发一个 ANALYZE 时追加到 autovacuum_analyze_threshold 参数上的表的尺寸之比例。缺省是 0.2。 这个选项只能在服务器启动的时候或者是在文件 postgresql.conf 里设置。 这个设置可以被 pg_autovacuum 表里面为每个表的独立条目覆盖。

autovacuum_vacuum_cost_delay (integer)

声明将在自动 VACUUM 操作里使用的开销延迟数值。 如果声明了 -1 (缺省值),那么将使用普通的 vacuum_cost_delay 数值。这个设置可以在 pg_autovacuum 表里面通过给不同的表设置不同的数据行来覆盖。

autovacuum_vacuum_cost_limit (integer)

声明将在自动的 VACUUM 操作里面使用的开销限制数值。 如果声明了 -1 (缺省值),那么将使用普通的 vacuum_cost_limit 数值。 这个设置可以在 pg_autovacuum 表里面通过给不同的表设置不同的数据行来覆盖。

 

vacuumdb

 

Name

vacuumdb -- 收集垃圾并且分析一个PostgreSQL 数据库

Synopsis

vacuumdb [connection-option...] [--full | -f] [--verbose | -v] [--analyze | -z] [--table | -t table [( column [,...] )] ] [dbname]
vacuumdb [connection-options...] [--all | -a] [--full | -f] [--verbose | -v] [--analyze | -z]

 

描述

vacuumdb 是一个用于整理 PostgreSQL 数据库的工具。 vacuumdb 还将会生成用于 PostgreSQL 查询优化器的内部统计数据。

vacuumdb 是 SQL 命令 VACUUM 的封装。 因此,用哪种方法清理数据库都没什么特别的。

 

输入

vacuumdb 接受下列命令行参数:

-a
--all

清理所有数据库。

[-d] dbname
[--dbname] dbname

声明要被清理或分析的数据库名称。 如果没有声明这个参数并且没有使用 -a(或 --all), 那么从环境变量 PGDATABASE 里读取数据库名。 如果那个也没有设置,则使用连接的用户名。

-e
--echo

回显 vacuumdb 生成的查询并且把它发送到服务器。

-f
--full

执行"完全"清理.

-q
--quiet

不显示响应。

-t table [ (column [,...]) ]
--table table [ (column [,...]) ]

只是清理或分析 table。 字段名称只是在与 --analyze 选项联合使用时才需要声明。

提示: 如果你声明了要清理的字段,你可能不得不在 shell 上逃逸圆括弧(见下面的例子)。

-v
--verbose

在处理过程中打印详细信息。

-z
--analyze

计算用于优化器的该数据库的统计值。

 

vacuumdb 还接受下面的命令行参数用于联接参数:

-h host
--host host

声明运行服务器的机器的主机名。 如果主机名以斜杠开头,则它被用做到 Unix 域套接字的路径。

-p port
--port port

声明服务器在侦听联接的 TCP 端口号或一个本地的 Unix 域套接字文件句柄。

-U username
--username username

进行联接的用户名。

-W
--password

强制口令输入提示。

 

 

环境

PGDATABASE
PGHOST
PGPORT
PGUSER

缺省连接参数

 

诊断

如果出差错了。参阅 VACUUMpsql 获取关于错误信息和可能问题的详细描述。 数据库服务器必须在目标主机上运行。同时,前端库 libpq 使用的任何缺省连接设置和环境变量都适用。

 

注意

vacuumdb 可能需要与 PostgreSQL 服务器连接若干次,每次都询问口令。在这种情况下,设立一个 ~/.pgpass 是比较方便的。参阅 Section 28.12 获取更多信息。

 

例子

整理数据库 test

$vacuumdb test

 

为优化器清理和分析一个名为 bigdb 的数据库:

$vacuumdb --analyze bigdb

 

为清理数据库xyzzy里表 foo, 并且为优化器分析列 bar

$vacuumdb --analyze --verbose --table 'foo(bar)' xyzzy


posted on 2011-11-16 10:18  jinshoucai  阅读(786)  评论(0)    收藏  举报