CLUSTER

Name

CLUSTER -- 根据一个索引对某个表盘簇化排序

Synopsis

CLUSTER [VERBOSE] _table_name_ [ USING _index_name_ ]
CLUSTER [VERBOSE]

描述

CLUSTER指示PostgreSQL基于索引_index_name_的内容对表_table_name_进行存储盘簇化排序。 索引必须已经在表_table_name_上定义过的索引。

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

在对一个表盘簇化排序之后,PostgreSQL会记忆使用了哪个索引上进行了盘簇化排序。 CLUSTER _table_name_的形式在表以前进行盘簇化排序的同一个索引上重新盘簇化排序。 也可以用CLUSTERSET WITHOUT CLUSTER形式来设置用于进行盘簇化排序的索引,或清除任何之前的设置。

不含参数的CLUSTER会将当前用户所拥有的当前数据库中的所有先前进行盘簇化排序的表重新处理,或者如果是超级用户使用这个命令时,则对所有进行过盘簇化排序表重新处理。 这种形式的CLUSTER不能在一个事务里面调用。

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

参数

_table_name_

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

_index_name_

一个索引名称。

VERBOSE

当每一个表进行盘簇化排序时打印一个处理情况报告。

注意

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

CLUSTER在盘簇化排序的处理过程中,可以按一个索引顺序,也可以按一个排序后的顺序扫描内容。 它会基于查询规划器的成本参数和表的统计信息选择一个相对较快的方法。

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