在PostgreSQL中,当指定多个列的组合作为PRIMARY KEY
时,记录是如何排序的?
这是假设 PostgreSQL 按照主键的顺序对记录进行排序。是吗?
此外,在 PostgreSQL 的情况下,主键是否自动索引?
最佳答案
这个问题误导了主键强加表顺序的假设。它没有。 PostgreSQL 表没有定义的顺序,有或没有主键;它们是按页 block 排列的行“堆”。需要时使用查询的 ORDER BY
子句进行排序。
您可能认为 PostgreSQL 表存储为以主键顺序存储在磁盘上的面向索引的表,但这不是 Pg 的工作方式。我认为 InnoDB 存储由主键组织的表(但尚未检查),并且它在其他一些供应商的数据库中是可选的,使用通常称为“聚集索引”或“索引组织表”的功能。 PostgreSQL 目前不支持此功能(至少从 9.3 开始)。
也就是说,PRIMARY KEY
是使用UNIQUE
索引实现的,并且该索引有一个顺序。它从索引的左列(因此也是主键)向前按升序排序,就好像它是 ORDER BY col1 ASC, col2 ASC, col3 ASC;
。 PostgreSQL 中的任何其他 b 树(不同于 GiST 或 GIN)索引也是如此,因为它们是使用 b+trees 实现的。 .
所以在表中:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
系统会自动创建等同于:
CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);
这会在您创建表时报告给您,例如:
regress=> CREATE TABLE demo (
regress(> a integer,
regress(> b text,
regress(> PRIMARY KEY(a,b)
regress(> );
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "demo_pkey" for table "demo"
CREATE TABLE
检查表时可以看到这个索引:
regress=> \d demo
Table "public.demo"
Column | Type | Modifiers
--------+---------+-----------
a | integer | not null
b | text | not null
Indexes:
"demo_pkey" PRIMARY KEY, btree (a, b)
您可以在此索引上CLUSTER
以根据主键对表重新排序,但这是一次性操作。系统不会维持该顺序 - 尽管如果页面中由于非默认 FILLFACTOR
有空闲空间,我认为它会尝试。
索引(而不是堆)的固有排序的一个结果是搜索速度多:
SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;
比:
SELECT * FROM demo ORDER BY a DESC, b;
并且这些都不能使用主键索引,除非你在 b
上有索引,否则它们将执行 seqscan:
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
这是因为 PostgreSQL 可以在 (a,b)
上使用索引几乎与单独在 (a)
上使用索引一样快。它不能在 (a,b)
上使用索引,就好像它是单独在 (b)
上的索引一样 - 甚至不能慢,它就是不能。
至于DESC
条目,对于那个Pg 必须进行反向索引扫描,这比普通的正向索引扫描慢。如果您在 EXPLAIN ANALYZE
中看到大量反向索引扫描,并且您可以承受额外索引的性能成本,您可以按 DESC
顺序在字段上创建索引。
WHERE
子句也是如此,而不仅仅是 ORDER BY
。您可以使用 (a,b)
上的索引来搜索 WHERE a = 4
或 WHERE a = 4 AND b = 3
但是 < em>不 单独搜索WHERE b = 3
。
关于postgresql - 具有复合主键的表中记录的顺序是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13190720/