在PostgreSQL中,当多个列的组合被指定为 时PRIMARY KEY
,记录是如何排序的?
这是假设 PostgreSQL 按照主键的顺序对记录进行排序。可以?
此外,在 PostgreSQL 的情况下,主键是否会自动编制索引?
在PostgreSQL中,当多个列的组合被指定为 时PRIMARY KEY
,记录是如何排序的?
这是假设 PostgreSQL 按照主键的顺序对记录进行排序。可以?
此外,在 PostgreSQL 的情况下,主键是否会自动编制索引?
这个问题做出了错误的假设,即主键根本就强加了表顺序。它没有。PostgreSQL 表没有定义的顺序,有或没有主键;它们是按页块排列的行“堆”。ORDER BY
需要时使用查询子句进行排序。
您可能会认为 PostgreSQL 表被存储为以主键顺序存储在磁盘上的面向索引的表,但这不是 Pg 的工作方式。我认为 InnoDB 存储由主键组织的表(但尚未检查),并且在其他一些供应商的数据库中使用通常称为“聚集索引”或“索引组织表”的功能是可选的。PostgreSQL 目前不支持此功能(至少从 9.3 开始)。
也就是说,它PRIMARY KEY
是使用UNIQUE
索引实现的,并且该索引有一个排序。它从索引的左列(因此是主键)开始按升序排序,就好像它是ORDER BY col1 ASC, col2 ASC, col3 ASC;
. PostgreSQL 中的任何其他 b-tree(与 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;
并且这些都不能使用主键索引,除非你有一个索引,否则它们会执行 seqscan b
:
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
这是因为 PostgreSQL 使用索引几乎和单独使用索引(a,b)
一样快。(a)
它不能像单独使用索引(a,b)
一样使用索引(b)
- 甚至不能缓慢,它就是不能。
至于DESC
entry,对于那个Pg,必须做一个反向索引扫描,比普通的正向索引扫描要慢。如果您看到大量反向索引扫描,EXPLAIN ANALYZE
并且您可以负担额外索引的性能成本,则可以按DESC
顺序在字段上创建索引。
这适用于WHERE
从句,而不仅仅是ORDER BY
. 您可以使用索引(a,b)
来搜索WHERE a = 4
或单独搜索,WHERE a = 4 AND b = 3
但不能单独搜索WHERE b = 3
。