PostgreSQL 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
CLUSTER
或者ALTER TABLE
的SET WITHOUT CLUSTER
形式把索引设置为可用于 未来的聚簇操作,或者清除任何之前的设置。
不带任何参数的CLUSTER
会重新聚簇调用用 户所拥有的当前数据库中已经被聚簇过的表(如果是超级用户调用,则是 所有已被聚簇过的表)。这种形式的 CLUSTER
不能在一个事务块内执行。
当一个表被聚簇时,会在其上要求一个ACCESS
EXCLUSIVE
锁。这会阻止任何其他数据库操作(包括读和写) 在CLUSTER
结束前在该表上操作。
参数
table_name
-
一个表的名称(可能是模式限定的)。
index_name
-
一个索引的名称。
VERBOSE
-
在每一个表被聚簇时打印一个进度报告。
注解
在随机访问一个表中的行时,表中数据的实际顺序是无关紧要的。 不过,如果你想要更多地访问其中一些数据,并且有一个索引把它 们分组在一起,使用CLUSTER
就会带 来好处。如果你从一个表中要求一个范围的被索引值或者多行都匹 配的一个单一值,CLUSTER
就会有所 帮助,因为一旦该索引标识出了第一个匹配行所在的表页,所有其 他匹配行很可能就在同一个表页中,并且因此节省了磁盘访问并且 提高了查询速度。
CLUSTER
可以使用指定索引上的一次索引扫描 或者遵循排序的一次顺序扫描(如果索引是 B 树)对表重新排序。 它将会基于规划器代价参数以及可用的统计信息来选择较快的方法。
在使用索引扫描时,会创建该表的一份临时拷贝,其中包含按索引顺序 排列的表数据。该表上每一个索引的临时拷贝也会被创建。因此,在磁 盘上需要至少等于表尺寸加上索引尺寸的综合的空闲空间。
在使用顺序扫描以及排序时,也会创建一个临时排序文件,因此临时空 间需求的峰值也就是表尺寸的两倍外加索引尺寸。这种方法通常比索引 扫描方法更快,但是如果磁盘空间需求是不能接受的,你可以通过临时 地把enable_sort设置为off
来禁 用这种选择。
建议在聚簇前把maintenance_work_mem设 置为一个合理地比较大的值(但是不能超过你可以用于 CLUSTER
操作的 RAM 容量)。
因为规划器会记录有关表顺序的统计信息,建议在新近被聚簇的表上 运行ANALYZE。否则,规划器可能会产生很差 的查询计划。
因为CLUSTER
会记住哪些索引被聚簇, 我们可以第一次手动聚簇想要聚簇的表,然后设置一个定期运行的维护 脚本,其中执行不带任何参数的CLUSTER
,这样那些 表就会被周期性地重新聚簇。
示例
基于索引employees_ind
聚簇表 employees
:
CLUSTER employees USING employees_ind;
使用之前用过的同一个索引聚簇employees
表:
CLUSTER employees;
对数据库中以前被聚簇过的所有表进行聚簇:
CLUSTER;
兼容性
在 SQL 标准中没有CLUSTER
语句。
为了兼容 8.3 之前的PostgreSQL版本,
CLUSTER index_name
ON table_name
语法也被支持。