CLUSTER — 将表根据索引聚簇
CLUSTER [ (option
[, ...] ) ] [table_name
[ USINGindex_name
] ] whereoption
can be one of: VERBOSE [boolean
]
CLUSTER
指示 PostgreSQL 将由 table_name
指定的表基于由 index_name
指定的索引进行聚簇。该索引必须已经在 table_name
上进行定义。
簇集表后,会根据索引信息按物理方式对其重新排序。簇集是一次性操作:表随后更新时,将不会进行簇集。也就是说,不会尝试按照索引顺序存储新增或更新的行。(如果愿意,可以随时通过再次发出该命令进行重新簇集。此外,将表的fillfactor
存储参数设置为小于 100% 有助于在更新期间保留簇集顺序,因为如果有足够可用空间,将会在同一页上保留更新的行。)
簇集表后,PostgreSQL 将记住按哪个索引对其进行簇集。格式 CLUSTER
会使用之前相同的索引对该表进行重新簇集。还可以使用 table_name
ALTER TABLE
的CLUSTER
或SET WITHOUT CLUSTER
格式来设置用于未来簇集操作的索引,或清除所有先前的设置。
CLUSTER
如果不带table_name
,将对当前数据库中所有先前已簇集的表进行重新簇集,条件是调用用户拥有对应权限。这种格式的CLUSTER
不能在事务块中执行。
簇集表时,将对其获取ACCESS EXCLUSIVE
锁。在CLUSTER
完成之前,这将阻止其他任何数据库操作(包括读写)在该表上进行操作。
table_name
表的名称(可能带有模式限定)。
index_name
索引的名称。
VERBOSE
在每个表簇集时打印进度报告。
boolean
指定应启用还是禁用已选选项。可以编写TRUE
、ON
或1
来启用该选项,以及FALSE
、OFF
或0
来禁用该选项。boolean
值也可以省略,在这种情况下,将假设为TRUE
。
要簇集表,必须具有对该表的MAINTAIN
权限。
在您随机访问表中的单行的情况下,表中数据的实际顺序并不重要。但是,如果您倾向于访问某些数据超过其他数据,并且有一个将它们分组在一起的索引,那么您将受益于使用 CLUSTER
。如果您从表中请求范围索引值,或者匹配多行的单一的索引值,CLUSTER
将有所帮助,因为一旦索引识别出匹配第一行的表页,所有其他匹配行可能已经在同一个表页上,从而节省磁盘访问并加快查询。
CLUSTER
可以使用指定索引上的索引扫描,或(如果索引是 b 树)一个顺序扫描,然后排序,重新对表进行排序。它将尝试选择基于规划器成本参数和可用的统计信息,将更快的那个方法。
当 CLUSTER
运行时,search_path 将暂时更改为 pg_catalog, pg_temp
。
当使用索引扫描时,将创建包含以索引顺序排列的表数据的表的临时副本。也会创建表上每个索引的临时副本。因此,您需要磁盘上的空余空间至少等于表大小和索引大小的总和。
当使用顺序扫描和排序时,也会创建一个临时排序文件,以便临时的峰值空间需求高达表大小的两倍,加上索引大小。此方法通常比索引扫描方法快,但是如果磁盘空间需求不可容忍,您可以通过将 enable_sort 暂时设置为 off
来禁用此选择。
在做 cluster 之前,建议将 maintenance_work_mem 设置为相当大的值(但不要超过可以专门用于 CLUSTER
操作的 RAM 量)。
因为规划器记录关于表顺序的统计信息,所以建议在新的集群表上运行 ANALYZE
。否则,规划器可能会对查询计划做出糟糕的选择。
由于 CLUSTER
可记住哪些索引是已聚集的,因此,可以第一次手动聚集希望聚集的表,然后设置一个定期执行 CLUSTER
(无任何参数)的维护脚本,以便定期对目标表重新聚集。
每个运行 CLUSTER
的后端将在 pg_stat_progress_cluster
视图中报告其进度。有关详细信息,请参阅 第27.4.2节。
聚集分区表会使用指定分区索引的分区来聚集其每个分区。在聚集分区表时,不能省略索引。对于分区表,不能在事务块内执行 CLUSTER
。
基于其索引 employees_ind
聚集表 employees
CLUSTER employees USING employees_ind;
使用之前已使用的相同索引,聚集 employees
表
CLUSTER employees;
聚集数据库中先前已聚集的所有表
CLUSTER;
SQL 标准中没有 CLUSTER
语句。
以下语法在 PostgreSQL 17 之前使用,并且仍然支持
CLUSTER [ VERBOSE ] [table_name
[ USINGindex_name
] ]
以下语法在 PostgreSQL 8.3 之前使用,并且仍然支持
CLUSTERindex_name
ONtable_name