©
本文档使用
php.cn手册 发布
CLUSTER [VERBOSE] table_name [ USING index_name ] CLUSTER [VERBOSE]
CLUSTER指示PostgreSQL基于索引table_name的度量对表index_name进行存储群集。 索引必须已经在表table_name上定义。
当对一个表群集后,该表的物理存储将基于索引信息进行。群集是一次性操作:当表将来被更新之后, 更改的内容不会被群集。也就是说,系统不会试图按照索引顺序对更新过的记录重新群集。(如果需要, 可以通过周期性地手工执行该命令的方法重新群集。并且,设置表的FILLFACTOR 存储参数为小于100%可以帮助保持集群在更新时排序,因为若有足够的空间可用,更新的行可以保存在 相同的页面。)
在对一个表群集之后,PostgreSQL会记忆在哪个索引上建立了群集。 CLUSTER table_name 的形式就在表以前群集的同一个索引上重新群集。您也可以用ALTER TABLE 的 CLUSTER或SET WITHOUT CLUSTER形式来设置索引来 用于未来集群操作,或清除任何之前的设置。
不含参数的CLUSTER重聚集调用用户拥有的当前数据库中的所有先前聚集的表, 或者若被超级用户调用就是所有这些表。 这种形式的CLUSTER不能在一个事务或者函数里面调用。
在对一个表进行群集的时候,会在其上请求一个ACCESS EXCLUSIVE锁。这样就避免了在CLUSTER完成之前执行任何其它 的数据库操作(包括读写)。
表的名称(可以有模式修饰)。
一个索引名称。
打印一个进度报告,因为每个表都是集群的。
如果你只是随机的访问表中的行,那么表中数据的实际存储顺序是无关紧要的。但是, 如果对某些数据的访问多于其它数据,而且有一个索引将这些数据分组, 那么将从使用CLUSTER中获益。如果从一个表中请求一定索引范围的值, 或者是一个索引值对应多行,CLUSTER也会有助于应用,因为如果索引 标识出第一匹配行所在的存储页,所有其它行也可能已经在同一个存储页里了,这样便节省 了磁盘访问的时间,加速了查询。
在这个群集的操作过程中,系统先创建一个按照索引顺序建立的表的临时拷贝。 同时也建立表上的每个索引的临时拷贝。因此,需要磁盘上有足够的剩余空间, 至少是表大小和索引大小的和。
因为CLUSTER记忆群集信息,可以在第一次的时候手工对 表进行群集,然后设置一个类似VACUUM的时间,这样就可以 周期地自动对表进行群集操作。
因为规划器记录着有关表的排序的统计,所以建议在新近群集的表上运行 ANALYZE。否则,规划器可能会选择很差劲的查询规划。
还有另外一种群集数据的方法。CLUSTER命令将原表按你 声明的索引重新排列。这个动作在操作大表时可能会很慢,因为每一行都按索引 顺序取出,所以如果表没有排序,那么整个表就是随机存放在各个页面里的, 因而每移动一行都要进行一次磁盘页面操作。PostgreSQL 有一个缓冲,但一个大表的主体是不可能都放到缓冲去的。这种对表群集的另外方法是:
CREATE TABLE newtable AS SELECT * FROM table ORDER BY columnlist;
这个用法使用PostgreSQL排序代码来创建一个需要的顺序, 在对未排序的数据操作时速度通常比索引扫描快得多。 然后你可以删除旧表,用ALTER TABLE ... RENAME 将newtable改成旧表名, 并且重建该表的所有索引。但是,这个方法不保留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版本的兼容。