阅读(3423) (11)

PostgreSQL CLUSTER

2021-08-23 14:26:48 更新

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 TABLESET 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

语法也被支持。

另见

clusterdb