问题报告 纠错本页面

CLUSTER

名称

CLUSTER -- 根据某个索引聚簇一个表

大纲

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

描述

CLUSTER指示PostgreSQL基于index_name指定的索引聚簇由table_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在重新排序表时,可以使用指定索引上的一个索引扫描,或者(如果索引是b-tree)可以使用顺序扫描再跟一个排序操作。 它会基于查询规划器的成本参数和表的统计信息选择一个相对较快的方法。

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

当使用顺序扫描和排序操作时,系统会创建临时排序文件,这样极端情况下,磁盘空间会需要至少约2倍的表大小和索引大小。 这个方法一般比使用索引的方法要快一点,但如果对磁盘空间的要求不可接受,可以临时设置enable_sortoff来禁用这个选择。

建议在执行聚簇前,将maintenance_work_mem参数设置为一个合理的较大数值(但不要超过可以保留给CLUSTER使用的内存大小)。

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

因为CLUSTER记录着哪些索引用于过聚簇,所以用户可以第一次手工指定表使用指定索引进行聚簇,以后设置一个周期化执行的维护脚本,只需执行不带参数的CLUSTER命令,即可实现对想要周期性聚簇的表进行自动更新。

例子

按照索引employees_ind的顺序对employees表进行聚簇:

CLUSTER employees USING employees_ind;

使用以前用过的同一个索引对employees表进行聚簇:

CLUSTER employees;

对以前聚簇过的所有表重新聚簇:

CLUSTER;

兼容性

SQL标准里没有CLUSTER语句。

 CLUSTER index_name ON table_name

的语法也兼容PostgreSQL 8.3之前的版本

参见

clusterdb