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

Abh*_*ain 17 sorting postgresql primary-key

在PostgreSQL中,当指定多列的组合时PRIMARY KEY,如何排序记录?

这是假设PostgreSQL按主键的顺序排序记录.可以?

另外,在PostgreSQL的情况下,主键是否自动编入索引?

Cra*_*ger 43

这个问题误导了主键强加一个表顺序.它没有.PostgreSQL表没有定义的顺序,有或没有主键; 它们是页面块中排列的行的"堆".ORDER BY在需要时使用查询子句强制进行排序.

您可能认为PostgreSQL表存储为面向索引的表,这些表以主键顺序存储在磁盘上,但这不是Pg的工作方式.我认为InnoDB存储由主键组织的表(但尚未检查),并且在一些其他供应商的数据库中使用通常称为"聚簇索引"或"索引组织表"的功能是可选的.PostgreSQL目前不支持此功能(至少从9.3开始).

也就是说,PRIMARY KEY使用UNIQUE索引实现,并且对该索引进行排序.它从索引的左列(以及主键)开始按升序排序,就好像它一样ORDER BY col1 ASC, col2 ASC, col3 ASC;.PostgreSQL中的任何其他b树(与GiST或GIN不同)索引也是如此,因为它们是使用b +树实现的.

所以在表中:

CREATE TABLE demo (
   a integer,
   b text, 
   PRIMARY KEY(a,b)
);
Run Code Online (Sandbox Code Playgroud)

系统将自动创建相当于:

CREATE UNIQUE INDEX demo_pkey ON demo(a ASC, b ASC);
Run Code Online (Sandbox Code Playgroud)

创建表时会向您报告,例如:

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
Run Code Online (Sandbox Code Playgroud)

检查表时可以看到此索引:

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)
Run Code Online (Sandbox Code Playgroud)

您可以CLUSTER在此索引上根据主键重新排序表,但这是一次性操作.系统不会保持这种顺序 - 但如果由于非默认值而在页面中有空闲空间,FILLFACTOR我认为它会尝试.

索引(但不是堆)的固有排序的一个结果是搜索速度快得多:

SELECT * FROM demo ORDER BY a, b;
SELECT * FROM demo ORDER BY a;
Run Code Online (Sandbox Code Playgroud)

比:

SELECT * FROM demo ORDER BY a DESC, b;
Run Code Online (Sandbox Code Playgroud)

并且它们都不能使用主键索引,除非你有索引,否则它们会执行seqscan b:

SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
Run Code Online (Sandbox Code Playgroud)

这是因为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孤独.

  • @AbhishekJain欢迎你.我强烈建议你熟悉`EXPLAIN ANALYZE`命令,并使用`psql`命令shell.两者都将帮助您了解PostgreSQL如何更好地工作,分析查询的执行方式,测试不同的索引策略等.http://explain.depesz.com/在尝试理解大型和复杂的查询计划时也很有用. (2认同)