62

我正在使用 psql 访问 postgres 数据库。在查看表的元数据时,有什么方法可以查看表的索引是否为聚集索引?

听说表的 PRIMARY KEY 会自动关联聚集索引,是真的吗?

4

6 回答 6

53

请注意,PostgreSQL 使用术语“聚集索引”来使用与 SQL Server 模糊相似但又非常不同的东西。

如果某个特定索引已被指定为表的聚集索引,则 psql 的\d命令将指示聚集索引,例如,

Indexes:
    "timezone_description_pkey" PRIMARY KEY, btree (timezone) CLUSTER

默认情况下,PostgreSQL 不指定索引作为集群索引。即使如此指定,它也不会自动排列表数据以与聚簇索引相关:必须使用 CLUSTER 命令来重新组织表数据。

于 2011-01-25T17:17:16.323 回答
29

在 PostgreSQL 中,聚集属性保存在相应索引的元数据中,而不是关系本身。它是pg_index目录中的indisclustered属性。但是请注意,postgres 中的聚类关系是一次性操作:即使该属性为真,对表的更新也不会保持数据的排序性质。迄今为止,数据聚类的自动维护仍然是一个流行的TODO项目。

聚集索引和集成索引之间经常存在混淆,特别是因为流行的教科书使用了相互冲突的名称,并且 postgres 和 SQL server 的手册中的术语再次不同(仅举两个例子)。当我谈论集成索引(也称为主索引主索引)时,我的意思是关系数据包含在索引的叶子中,而不是外部二级索引,其中叶子包含指向的索引条目到表记录。前一种类型必然总是聚集的。不幸的是 postgres 只支持后一种类型。无论如何,事实是一个集成的(主)索引总是聚集的可能已经引起了“表的主键自动与聚集索引相关联”的信念。这两种说法听起来相似,但又有所不同。

于 2011-10-17T05:00:30.767 回答
26

有什么方法可以查看表的索引是否为聚集索引

PostgreSQL 没有聚集索引,因此您将无法看到它们。

听说表的 PRIMARY KEY 会自动关联聚集索引,是真的吗?

不,那不是真的(见上文)

您可以沿着索引手动将表聚集在一起,但这不会自动维护(例如,使用 SQL Server 的聚集索引)。

更多详细信息,请参见手册中对CLUSTER命令的说明。

于 2011-01-25T17:16:20.660 回答
24

PostgreSQL 没有像 Microsoft SQL Server 那样直接实现 CLUSTER 索引。

来自此博客的参考资料:

在 PostgreSQL 中,我们有一个类似于 Cluster Index 的 CLUSTER 命令。

创建表主键或任何其他索引后,您可以通过指定该索引名称来执行 CLUSTER 命令以实现表数据的物理顺序。

当一个表被聚集时,它会根据索引信息在物理上重新排序。集群是一次性操作:当表随后更新时,更改不会集群。也就是说,不会尝试根据索引顺序存储新的或更新的行。

集群语法:

第一次必须使用索引名称执行 CLUSTER。

CLUSTER table_name USING index_name;

对表进行聚类:

一旦你用索引执行了 CLUSTER,下次你应该只执行 CLUSTER TABLE,因为它知道哪个索引已经定义为 CLUSTER。

CLUSTER table_name;
于 2016-12-03T18:25:23.853 回答
13

集群索引

集群索引意味着告诉数据库将实际接近的值存储在磁盘上。它们可以唯一标识 SQL 表中的行。每个表都可以只有一个聚集索引。一个聚集索引可以覆盖多个列。默认情况下,具有主键的列已经具有聚集索引。

字典

字典本身就是一个带有聚集索引的表。因为所有数据都是按字母顺序物理存储的。


非集群索引

非聚集索引就像一本书的简单索引。它们仅用于快速检索数据。不确定是否有唯一数据。非聚集索引包含非聚集索引键及其对应的数据位置指针。例如,一本书的内容索引包含主题或章节的关键字以及该主题或章节的页面位置。

图书内容索引

一本书的内容表包含内容名称及其页面位置。不确定数据是否唯一。因为可以多次放置相同的段落或文本行或单词。


PostgreSQL 索引

PRIMARY KEYPostgreSQL 自动为表的每个UNIQUE约束创建索引。登录到 PostgreSQL 终端中的数据库并输入 \d table_name. 所有存储的索引都将被可视化。如果有聚集索引,那么它也会被识别。

创建表

CREATE TABLE IF NOT EXISTS profile(
    uid serial NOT NULL UNIQUE PRIMARY KEY,
    username varchar(30) NOT NULL UNIQUE,
    phone varchar(11) NOT NULL UNIQUE,
    age smallint CHECK(age>12),
    address text NULL
);

3索引将自动创建。所有这些索引都是非聚集的

"profile_pkey" PRIMARY KEY, btree (uid)
"profile_phone_key" UNIQUE CONSTRAINT, btree (phone)
"profile_username_key" UNIQUE CONSTRAINT, btree (username)

使用 uid 和用户名创建我们自己的索引

CREATE INDEX profile_index ON profile(uid, username);

这实际上创建了一个非聚集索引。要使其集群化,请运行下一部分。

将非聚集索引转换为聚集索引

ALTER TABLE profile CLUSTER ON profile_index;

用 . 检查表\d profile。它会是这样的:

                                     Table "public.profile"
  Column  |         Type          | Collation | Nullable |               Default
----------+-----------------------+-----------+----------+--------------------------------------
 uid      | integer               |           | not null | nextval('profile_uid_seq'::regclass)
 username | character varying(30) |           | not null |
 phone    | character varying(11) |           | not null |
 age      | smallint              |           |          |
 address  | text                  |           |          |
Indexes:
    "profile_pkey" PRIMARY KEY, btree (uid)
    "profile_phone_key" UNIQUE CONSTRAINT, btree (phone)
    "profile_username_key" UNIQUE CONSTRAINT, btree (username)
    "profile_index" btree (uid, username) CLUSTER
Check constraints:
    "profile_age_check" CHECK (age > 12)

请注意,profile_index 现在是“CLUSTER”

现在,重新对表进行集群,以便表可以遵循集群索引角色

CLUSTER profile;
于 2019-03-29T05:58:24.947 回答
6

如果您想知道给定的表是否CLUSTER使用 SQL 编辑,您可以使用以下查询来显示正在使用的索引(在 Postgres 版本 9.5 和 9.6 中测试):

SELECT
  i.relname AS index_for_cluster
FROM
  pg_index AS idx
JOIN
  pg_class AS i
ON
  i.oid = idx.indexrelid
WHERE
  idx.indisclustered
  AND idx.indrelid::regclass = 'your_table_name'::regclass;
于 2017-02-24T15:32:16.867 回答