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孤独.