2024 年 9 月 26 日: PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持的版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

CLUSTER

CLUSTER — 根据索引对表进行聚类

概要

CLUSTER [ ( option [, ...] ) ] [ table_name [ USING index_name ] ]

where option can be one of:

    VERBOSE [ boolean ]

描述

CLUSTER 指示 PostgreSQL 根据 index_name 指定的索引对由 table_name 指定的表进行聚类。该索引必须已在 table_name 上定义。

对表进行聚类时,它会根据索引信息进行物理重新排序。聚类是一次性操作:随后更新表时,不会对更改进行聚类。也就是说,不会尝试根据索引顺序存储新的或更新的行。(如果需要,可以定期通过再次发出命令来重新聚类。此外,将表的 fillfactor 存储参数设置为小于 100% 可以帮助在更新期间保留聚类顺序,因为如果有足够的空间,更新后的行会保留在同一页上。)

对表进行聚类时,PostgreSQL 会记住它所聚类的索引。形式 CLUSTER table_name 使用之前相同的索引对表进行重新聚类。您也可以使用 ALTER TABLECLUSTERSET WITHOUT CLUSTER 形式设置用于将来聚类操作的索引,或清除任何先前的设置。

CLUSTER 没有 table_name 会对当前数据库中调用用户有权限的所有先前已聚类的表进行重新聚类。这种形式的 CLUSTER 不能在事务块内执行。

对表进行聚类时,会获取该表的 ACCESS EXCLUSIVE 锁。这会阻止任何其他数据库操作(包括读取和写入)在 CLUSTER 完成之前对表进行操作。

参数

table_name

表的名称(可能是模式限定的)。

index_name

索引的名称。

VERBOSE

在对每个表进行聚类时打印进度报告。

boolean

指定是否应启用或禁用所选选项。您可以编写 TRUEON1 来启用该选项,编写 FALSEOFF0 来禁用该选项。也可以省略 boolean 值,在这种情况下,假定为 TRUE

注意

要对表进行聚类,必须对该表具有 MAINTAIN 权限。

在您随机访问表中的单个行的情况下,表中数据的实际顺序并不重要。但是,如果您倾向于访问某些数据而不是其他数据,并且有一个将它们分组在一起的索引,那么您将从使用 CLUSTER 中受益。如果您从表中请求一系列索引值,或者请求一个具有多个匹配行的单个索引值,则 CLUSTER 将有所帮助,因为一旦索引识别出与第一行匹配的表页,所有其他匹配行可能已在同一表页上,因此您可以节省磁盘访问次数并加快查询速度。

CLUSTER 可以使用在指定索引上进行索引扫描,或者(如果索引是 B 树)进行顺序扫描然后排序来对表进行重新排序。它将尝试根据规划程序成本参数和可用的统计信息选择速度更快的办法。

CLUSTER 运行期间,search_path 会暂时更改为 pg_catalog, pg_temp

当使用索引扫描时,会创建一个表的临时副本,其中包含按索引顺序排列的表数据。也会创建表上每个索引的临时副本。因此,您需要磁盘上至少等于表大小和索引大小之和的可用空间。

当使用顺序扫描和排序时,还会创建一个临时排序文件,因此峰值临时空间需求高达表大小的两倍,加上索引大小。这种方法通常比索引扫描方法快,但如果磁盘空间需求无法容忍,则可以通过暂时将 enable_sort 设置为 off 来禁用这种选择。

建议在聚类之前将 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 [ USING index_name ] ]

以下语法在 PostgreSQL 8.3 之前使用,现在仍然支持

CLUSTER index_name ON table_name

另请参见

clusterdb第 27.4.2 节

提交更正

如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符,或者需要进一步说明,请使用 此表格 报告文档问题。