CLUSTER

Name

CLUSTER -- 根据一个索引对某个表群集

Synopsis

CLUSTER [VERBOSE] table_name [ USING index_name ]
CLUSTER [VERBOSE]

描述

CLUSTER指示PostgreSQL基于索引table_name的度量对表index_name进行存储群集。 索引必须已经在表table_name上定义。

当对一个表群集后,该表的物理存储将基于索引信息进行。群集是一次性操作:当表将来被更新之后, 更改的内容不会被群集。也就是说,系统不会试图按照索引顺序对更新过的记录重新群集。(如果需要, 可以通过周期性地手工执行该命令的方法重新群集。并且,设置表的FILLFACTOR 存储参数为小于100%可以帮助保持集群在更新时排序,因为若有足够的空间可用,更新的行可以保存在 相同的页面。)

在对一个表群集之后,PostgreSQL会记忆在哪个索引上建立了群集。 CLUSTER table_name 的形式就在表以前群集的同一个索引上重新群集。您也可以用ALTER TABLECLUSTERSET WITHOUT CLUSTER形式来设置索引来 用于未来集群操作,或清除任何之前的设置。

不含参数的CLUSTER重聚集调用用户拥有的当前数据库中的所有先前聚集的表, 或者若被超级用户调用就是所有这些表。 这种形式的CLUSTER不能在一个事务或者函数里面调用。

在对一个表进行群集的时候,会在其上请求一个ACCESS EXCLUSIVE锁。这样就避免了在CLUSTER完成之前执行任何其它 的数据库操作(包括读写)。

参数

table_name

表的名称(可以有模式修饰)。

index_name

一个索引名称。

VERBOSE

打印一个进度报告,因为每个表都是集群的。

注意

如果你只是随机的访问表中的行,那么表中数据的实际存储顺序是无关紧要的。但是, 如果对某些数据的访问多于其它数据,而且有一个索引将这些数据分组, 那么将从使用CLUSTER中获益。如果从一个表中请求一定索引范围的值, 或者是一个索引值对应多行,CLUSTER也会有助于应用,因为如果索引 标识出第一匹配行所在的存储页,所有其它行也可能已经在同一个存储页里了,这样便节省 了磁盘访问的时间,加速了查询。

在这个群集的操作过程中,系统先创建一个按照索引顺序建立的表的临时拷贝。 同时也建立表上的每个索引的临时拷贝。因此,需要磁盘上有足够的剩余空间, 至少是表大小和索引大小的和。

因为CLUSTER记忆群集信息,可以在第一次的时候手工对 表进行群集,然后设置一个类似VACUUM的时间,这样就可以 周期地自动对表进行群集操作。

因为规划器记录着有关表的排序的统计,所以建议在新近群集的表上运行 ANALYZE。否则,规划器可能会选择很差劲的查询规划。

还有另外一种群集数据的方法。CLUSTER命令将原表按你 声明的索引重新排列。这个动作在操作大表时可能会很慢,因为每一行都按索引 顺序取出,所以如果表没有排序,那么整个表就是随机存放在各个页面里的, 因而每移动一行都要进行一次磁盘页面操作。PostgreSQL 有一个缓冲,但一个大表的主体是不可能都放到缓冲去的。这种对表群集的另外方法是:

CREATE TABLE newtable AS
    SELECT * FROM table ORDER BY columnlist;

这个用法使用PostgreSQL排序代码来创建一个需要的顺序, 在对未排序的数据操作时速度通常比索引扫描快得多。 然后你可以删除旧表,用ALTER TABLE ... RENAMEnewtable改成旧表名, 并且重建该表的所有索引。但是,这个方法不保留OID、约束、外键关系、赋予的权限 、以及其它附属的属性,所有这些属性都必须手工重建。另一个不利之处是这种方法需要 一个与原表大小相同的临时排序文件,所以所需磁盘空间将两倍于原表大小。

例子

按照雇员的employees_ind属性对employees表群集:

CLUSTER employees USING employees_ind;

使用以前用过的同一个索引对employees

CLUSTER employees;

对以前群集过的所有表进行群集:

CLUSTER;

兼容性

SQL标准里没有CLUSTER语句。

The syntax

CLUSTER index_name ON table_name

也支持对8.3之前的PostgreSQL版本的兼容。

又见

clusterdb