【发布时间】:2012-11-02 06:58:26
【问题描述】:
在PostgreSQL中,当多个列的组合被指定为PRIMARY KEY时,记录是如何排序的?
这是假设 PostgreSQL 按照主键的顺序对记录进行排序。是吗?
另外,如果是 PostgreSQL,主键会自动索引吗?
【问题讨论】:
标签: postgresql sorting primary-key
在PostgreSQL中,当多个列的组合被指定为PRIMARY KEY时,记录是如何排序的?
这是假设 PostgreSQL 按照主键的顺序对记录进行排序。是吗?
另外,如果是 PostgreSQL,主键会自动索引吗?
【问题讨论】:
标签: postgresql sorting primary-key
这个问题做出了错误的假设,即主键完全强制了表顺序。它没有。 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;
而且它们都不能使用主键索引,除非你在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,但不能 单独搜索WHERE b = 3。
【讨论】:
EXPLAIN ANALYZE 命令和psql 命令shell。两者都将帮助您了解 PostgreSQL 如何更好地工作、分析查询是如何执行的、测试不同的索引策略等。explain.depesz.com 在尝试理解大而复杂的查询计划时也很有用。