postgresql - 具有复合主键的表中记录的顺序是什么

标签 postgresql sorting primary-key

在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 = 4WHERE a = 4 AND b = 3 但是 < em>不 单独搜索WHERE b = 3

关于postgresql - 具有复合主键的表中记录的顺序是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13190720/

相关文章:

sql - 甲骨文 SQL : Receiving 'no matching unique or primary key' error and don't know why

java - 将一组随机整数从输入文件分配到 N 个输出(桶)文件的算法

php - GROUP BY 外键还是主键?

sql - 当我按键聚合时,为什么不能从 `GROUP BY` 中排除依赖列?

sql - PL/PgSQL 在 CREATE VIEW 中将变量名视为列名

python读取2个文件,忽略标题(#开头行),并对数据进行排序

java - 如何在 Java 的数组中按字母顺序对自定义对象进行排序?

php - 从 PHP 清理 PostgreSQL 数据库

ruby-on-rails - Rails 4 或 5,索引位于 Postgresql 中的 "updated_at"列。这是什么意思?

postgresql - PostGIS : schema is empty 的 pg_dump