我正在使用 psql 访问 postgres 数据库。在查看表的元数据时,有什么方法可以查看表的索引是否为聚集索引?
听说表的 PRIMARY KEY 会自动关联聚集索引,是真的吗?
我正在使用 psql 访问 postgres 数据库。在查看表的元数据时,有什么方法可以查看表的索引是否为聚集索引?
听说表的 PRIMARY KEY 会自动关联聚集索引,是真的吗?
请注意,PostgreSQL 使用术语“聚集索引”来使用与 SQL Server 模糊相似但又非常不同的东西。
如果某个特定索引已被指定为表的聚集索引,则 psql 的\d
命令将指示聚集索引,例如,
Indexes:
"timezone_description_pkey" PRIMARY KEY, btree (timezone) CLUSTER
默认情况下,PostgreSQL 不指定索引作为集群索引。即使如此指定,它也不会自动排列表数据以与聚簇索引相关:必须使用 CLUSTER 命令来重新组织表数据。
在 PostgreSQL 中,聚集属性保存在相应索引的元数据中,而不是关系本身。它是pg_index目录中的indisclustered
属性。但是请注意,postgres 中的聚类关系是一次性操作:即使该属性为真,对表的更新也不会保持数据的排序性质。迄今为止,数据聚类的自动维护仍然是一个流行的TODO项目。
聚集索引和集成索引之间经常存在混淆,特别是因为流行的教科书使用了相互冲突的名称,并且 postgres 和 SQL server 的手册中的术语再次不同(仅举两个例子)。当我谈论集成索引(也称为主索引或主索引)时,我的意思是关系数据包含在索引的叶子中,而不是外部或二级索引,其中叶子包含指向的索引条目到表记录。前一种类型必然总是聚集的。不幸的是 postgres 只支持后一种类型。无论如何,事实是一个集成的(主)索引总是聚集的可能已经引起了“表的主键自动与聚集索引相关联”的信念。这两种说法听起来相似,但又有所不同。
有什么方法可以查看表的索引是否为聚集索引
PostgreSQL 没有聚集索引,因此您将无法看到它们。
听说表的 PRIMARY KEY 会自动关联聚集索引,是真的吗?
不,那不是真的(见上文)
您可以沿着索引手动将表聚集在一起,但这不会自动维护(例如,使用 SQL Server 的聚集索引)。
更多详细信息,请参见手册中对CLUSTER命令的说明。
PostgreSQL 没有像 Microsoft SQL Server 那样直接实现 CLUSTER 索引。
在 PostgreSQL 中,我们有一个类似于 Cluster Index 的 CLUSTER 命令。
创建表主键或任何其他索引后,您可以通过指定该索引名称来执行 CLUSTER 命令以实现表数据的物理顺序。
当一个表被聚集时,它会根据索引信息在物理上重新排序。集群是一次性操作:当表随后更新时,更改不会集群。也就是说,不会尝试根据索引顺序存储新的或更新的行。
集群语法:
第一次必须使用索引名称执行 CLUSTER。
CLUSTER table_name USING index_name;
对表进行聚类:
一旦你用索引执行了 CLUSTER,下次你应该只执行 CLUSTER TABLE,因为它知道哪个索引已经定义为 CLUSTER。
CLUSTER table_name;
集群索引意味着告诉数据库将实际接近的值存储在磁盘上。它们可以唯一标识 SQL 表中的行。每个表都可以只有一个聚集索引。一个聚集索引可以覆盖多个列。默认情况下,具有主键的列已经具有聚集索引。
非聚集索引就像一本书的简单索引。它们仅用于快速检索数据。不确定是否有唯一数据。非聚集索引包含非聚集索引键及其对应的数据位置指针。例如,一本书的内容索引包含主题或章节的关键字以及该主题或章节的页面位置。
PRIMARY KEY
PostgreSQL 自动为表的每个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
);
"profile_pkey" PRIMARY KEY, btree (uid)
"profile_phone_key" UNIQUE CONSTRAINT, btree (phone)
"profile_username_key" UNIQUE CONSTRAINT, btree (username)
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;
如果您想知道给定的表是否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;