Postgresql - Cluster

CLUSTER — cluster a table according to an index

根据索引对表进行聚类

cluster指示postgresql根据index_name指定的索引对table_name指定的表进行集群。表上必须已经有索引。

当表被cluster时,它将根据索引信息进行物理重新排序。cluster是一次性操作:当表随后被更新时,更新不会被cluster。也就是说,不尝试根据新行或更新行的索引顺序存储新行或更新行。如果愿意,可以通过再次发出命令来定期重新调整。此外,将表的填满因子存储参数设置为小于100%有助于在更新期间保留群集顺序,因为如果有足够的空间,更新的行将保留在同一页上。)

当一个表被cluster 时,PostgreSQL会记住它被cluster 的索引。表单cluster table_name使用与以前相同的索引重新排序表。您还可以使用 cluster 或set without cluster form of alter table来设置将来cluster 操作要使用的索引,或者清除任何以前的设置。

不带任何参数的CLUSTER将重新对调用用户拥有的当前数据库中以前的所有聚集表进行排序,或者对超级用户调用的所有此类表进行排序。这种形式的集群不能在事务块内执行。

当一个表被cluster 时,它会获得一个访问排它锁。这将防止在集群完成之前对表进行任何其他数据库操作(读和写)。

执行参数:

table_name: 表名

index_name: 索引名。

berbose: 在每个表都聚集时打印进度报告。

在随机访问表中的单行的情况下,表中数据的实际顺序并不重要。但是,如果倾向于比其他人更多地访问一些数据,并且有一个索引将这些数据分组在一起,那么将从使用cluster中获益。如果从一个表中请求一个索引值范围,或者一个索引值有多个匹配的行,那么cluster将有所帮助,因为一旦索引为第一个匹配的行标识了表页,那么所有其他匹配的行可能已经在同一个表页上,因此可以保存磁盘访问并加快查询速度。

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

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

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

建议在cluster 之前将 maintenance_work_mem 设置为一个相当大的值(但不超过您可以专门用于集群操作的RAM数量)。

因为计划器记录有关表顺序的统计信息,所以建议对新cluster 的表运行分析。否则,计划者可能会对查询计划做出错误的选择。

因为cluster 记住了哪些索引是cluster 的,所以可以对第一次需要手动cluster 的表进行cluster ,然后设置一个周期性维护脚本,在不使用任何参数的情况下执行集群,以便周期性地重新集群所需的表。

===========================================================================================

-- 实验环境:CentOS 7 + PG 11.1
-- 说明:实验SQL是根据 digoal 的实验,自己亲手做的。感谢德哥!!!
-- 创建实验表,索引
create table test (id int, val numeric);
create index on test(id);
create index on test(val);

-- 插入实验数据
insert into test select generate_series(1,10000000),random();

-- 表信息
\d test
                Table "public.test"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 id     | integer |           |          |
 val    | numeric |           |          |
Indexes:
    "test_id_idx" btree (id)
    "test_val_idx" btree (val)

-- 表文件
select pg_relation_filepath('test'::regclass);
 pg_relation_filepath
----------------------
 base/16385/64278
(1 row)
-- 索引文件
select pg_relation_filepath('test_id_idx'::regclass);
 pg_relation_filepath
----------------------
 base/16385/64280
(1 row)
-- 索引文件
select pg_relation_filepath('test_val_idx'::regclass);
 pg_relation_filepath
----------------------
 base/16385/64281
(1 row)


-- 查看列的离散程度,值越接近0,表示越离散,越接近1,表示存储比较有顺序
-- 说明目前表是根据 id 有序存储的。
select correlation from pg_stats where tablename='test' and attname='id';
 correlation
-------------
           1

select correlation from pg_stats where tablename='test' and attname='val';
 correlation
-------------
  0.00781794
(1 row)

-- 收缩表,分析表,收集统计信息。
vacuum analyze test;

-- 最小的ID的存储位置
select ctid,id,val from test where id=(select min(id) from test);
 ctid  | id |        val
-------+----+-------------------
 (0,1) |  1 | 0.419486843980849
(1 row)

-- 最小的 VAL 的存储位置
select ctid,id,val from test where val=(select min(val) from test);
    ctid    |   id   |          val
------------+--------+------------------------
 (4361,127) | 806540 | 0.00000218348577618599
(1 row)


-- 根据 val 列上的索引。做cluster。
cluster test USING test_val_idx;

-- 查看最小 id 的存储
select ctid,id,val from test where id=(select min(id) from test);
   ctid   | id |        val
----------+----+-------------------
 (3192,7) |  1 | 0.589303761254996
(1 row)

-- 查看最小 val 的存储
select ctid,id,val from test where val=(select min(val) from test);
 ctid  |   id   |          val
-------+--------+------------------------
 (0,1) | 806540 | 0.00000218348577618599
(1 row)

-- 收缩表,分析表,收集统计信息。
vacuum analyze test;

-- 查看列的离散程度,值越接近0,表示越离散,越接近1,表示存储比较有顺序
-- 说明目前表是根据 val 有序存储的。
select correlation from pg_stats where tablename='test' and attname='val';
 correlation
-------------
           1
(1 row)

select correlation from pg_stats where tablename='test' and attname='id';
 correlation
-------------
  0.00133778
(1 row)

-- 查询表,索引文件,都变了。说明cluster重建表和索引。
select pg_relation_filepath('test'::regclass);
 pg_relation_filepath
----------------------
 base/16385/64283
(1 row)

select pg_relation_filepath('test_id_idx'::regclass);
 pg_relation_filepath
----------------------
 base/16385/64289
(1 row)

select pg_relation_filepath('test_val_idx'::regclass);
 pg_relation_filepath
----------------------
 base/16385/64290
(1 row)

-- 表锁
-- session 1
mytest=# begin;
BEGIN
mytest=# cluster test USING test_id_idx ;
CLUSTER

-- session 2
mytest=# select * from test limit 1;
等待......

-- session 3
select pid,locktype,database,relation,granted,mode,b.relname from pg_locks a,pg_class b where a.relation=b.oid;
  pid  | locktype | database | relation | granted |        mode         |              relname
-------+----------+----------+----------+---------+---------------------+-----------------------------------
 22891 | relation |    16385 |     3455 | t       | AccessShareLock     | pg_class_tblspc_relfilenode_index
 22891 | relation |    16385 |     2663 | t       | AccessShareLock     | pg_class_relname_nsp_index
 22891 | relation |    16385 |     2662 | t       | AccessShareLock     | pg_class_oid_index
 22891 | relation |    16385 |     1259 | t       | AccessShareLock     | pg_class
 22891 | relation |    16385 |    11645 | t       | AccessShareLock     | pg_locks
 21609 | relation |    16385 |     2679 | t       | AccessShareLock     | pg_index_indexrelid_index
 21609 | relation |    16385 |     2678 | t       | AccessShareLock     | pg_index_indrelid_index
 21609 | relation |    16385 |     2610 | t       | AccessShareLock     | pg_index
 21609 | relation |    16385 |     3455 | t       | AccessShareLock     | pg_class_tblspc_relfilenode_index
 21609 | relation |    16385 |     2663 | t       | AccessShareLock     | pg_class_relname_nsp_index
 21609 | relation |    16385 |     2662 | t       | AccessShareLock     | pg_class_oid_index
 21609 | relation |    16385 |     2685 | t       | AccessShareLock     | pg_namespace_oid_index
 21609 | relation |    16385 |     2684 | t       | AccessShareLock     | pg_namespace_nspname_index
 21609 | relation |    16385 |     2615 | t       | AccessShareLock     | pg_namespace
 21609 | relation |    16385 |     1259 | t       | AccessShareLock     | pg_class
 21609 | relation |    16385 |    64276 | t       | AccessShareLock     | test_val_idx
 21609 | relation |    16385 |    64276 | t       | AccessExclusiveLock | test_val_idx
 21609 | relation |    16385 |    64272 | t       | AccessExclusiveLock | pg_toast_64269
 21609 | relation |    16385 |    64275 | t       | AccessShareLock     | test_id_idx
 21609 | relation |    16385 |    64275 | t       | AccessExclusiveLock | test_id_idx
 21609 | relation |    16385 |    64269 | t       | ShareLock           | test
 21609 | relation |    16385 |    64269 | t       | AccessExclusiveLock | test
 22829 | relation |    16385 |    64269 | f       | AccessShareLock     | test
(23 rows)

猜你喜欢

转载自blog.csdn.net/chuckchen1222/article/details/85630528