CLUSTER — 根据一个索引聚簇一个表
CLUSTER [VERBOSE]table_name
[ USINGindex_name
] CLUSTER (option
[, ...] )table_name
[ USINGindex_name
] CLUSTER [VERBOSE]option
可以是以下之一: VERBOSE [boolean
]
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
在每一个表被聚簇时打印一个进度报告。
boolean
指定打开还是关闭选定的选项。你可以输入TRUE
、
ON
或1
启用该选项,
或者输入FALSE
、OFF
或0
禁用它。
也可以省略这个boolean
值,
在这种情况下,假设其值为TRUE
。
在随机访问一个表中的行时,表中数据的实际顺序是无关紧要的。
不过,如果你想要更多地访问其中一些数据,并且有一个索引把它
们分组在一起,使用CLUSTER
就会带
来好处。如果你从一个表中要求一个范围的被索引值或者多行都匹
配的一个单一值,CLUSTER
就会有所
帮助,因为一旦该索引标识出了第一个匹配行所在的表页,所有其
他匹配行很可能就在同一个表页中,并且因此节省了磁盘访问并且
提高了查询速度。
CLUSTER
可以使用指定索引上的一次索引扫描
或者遵循排序的一次顺序扫描(如果索引是 B 树)对表重新排序。
它将会基于规划器代价参数以及可用的统计信息来选择较快的方法。
在使用索引扫描时,会创建该表的一份临时拷贝,其中包含按索引顺序 排列的表数据。该表上每一个索引的临时拷贝也会被创建。因此,在磁 盘上需要至少等于表尺寸加上索引尺寸的综合的空闲空间。
在使用顺序扫描以及排序时,也会创建一个临时排序文件,因此临时空
间需求的峰值也就是表尺寸的两倍外加索引尺寸。这种方法通常比索引
扫描方法更快,但是如果磁盘空间需求是不能接受的,你可以通过临时
地把enable_sort设置为off
来禁
用这种选择。
建议在聚簇前把maintenance_work_mem设
置为一个合理地比较大的值(但是不能超过你可以用于
CLUSTER
操作的 RAM 容量)。
因为规划器会记录有关表顺序的统计信息,建议在新近被聚簇的表上
运行ANALYZE
。否则,规划器可能会产生很差
的查询计划。
因为CLUSTER
会记住哪些索引被聚簇,
我们可以第一次手动聚簇想要聚簇的表,然后设置一个定期运行的维护
脚本,其中执行不带任何参数的CLUSTER
,这样那些
表就会被周期性地重新聚簇。
运行CLUSTER
的每个后端将在
pg_stat_progress_cluster
视图中报告其进度。
有关详细信息,请参见第 28.4.4 节。
对分区表进行聚集会使用指定分区索引的分区来对每个分区进行聚集。在对分区表进行聚集时,索引不可省略。
基于索引employees_ind
聚簇表
employees
:
CLUSTER employees USING employees_ind;
使用之前用过的同一个索引聚簇employees
表:
CLUSTER employees;
对数据库中以前被聚簇过的所有表进行聚簇:
CLUSTER;
在 SQL 标准中没有CLUSTER
语句。
为了兼容 8.3 之前的PostgreSQL版本,
CLUSTERindex_name
ONtable_name
语法也被支持。