Postgresql 具有复合主键的表中记录的顺序是什么
在PostgreSQL中,当将多列的组合指定为主键时,记录是如何排序的 这是假设PostgreSQL按照主键的顺序对记录进行排序。是吗Postgresql 具有复合主键的表中记录的顺序是什么,postgresql,sorting,primary-key,Postgresql,Sorting,Primary Key,在PostgreSQL中,当将多列的组合指定为主键时,记录是如何排序的 这是假设PostgreSQL按照主键的顺序对记录进行排序。是吗 此外,对于PostgreSQL,主键是否会自动索引?这个问题错误地假设主键会强制执行表顺序。没有。PostgreSQL表没有定义的顺序,有或没有主键;它们是一堆按页面块排列的行。如果需要,可以使用查询的ORDER BY子句进行排序 您可能认为PostgreSQL表是作为面向索引的表存储的,这些表以主键顺序存储在磁盘上,但Pg不是这样工作的。我认为InnoDB存储
此外,对于PostgreSQL,主键是否会自动索引?这个问题错误地假设主键会强制执行表顺序。没有。PostgreSQL表没有定义的顺序,有或没有主键;它们是一堆按页面块排列的行。如果需要,可以使用查询的
ORDER BY
子句进行排序
您可能认为PostgreSQL表是作为面向索引的表存储的,这些表以主键顺序存储在磁盘上,但Pg不是这样工作的。我认为InnoDB存储按主键组织的表(但尚未选中),在其他一些供应商的数据库中,它是可选的,使用一种通常称为“聚集索引”或“索引组织表”的功能。PostgreSQL目前不支持此功能(至少从9.3开始)
这就是说,主键
是使用唯一
索引实现的,并且该索引有一个顺序。它从索引的左列(因此也是主键)开始按升序排序,就好像它是按col1 ASC、col2 ASC、col3 ASC排序的代码>。PostgreSQL中的任何其他b树(不同于GiST或GIN)索引也是如此,因为它们是使用实现的
因此,在表中:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
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)
系统将自动创建以下等效项:
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
检查表格时,您可以看到此索引:
CREATE TABLE demo (
a integer,
b text,
PRIMARY KEY(a,b)
);
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;
比:
这两个都不能使用主键索引,它们将执行seqscan,除非您在b
上有索引:
SELECT * FROM demo ORDER BY b, a;
SELECT * FROM demo ORDER BY b;
这是因为PostgreSQL在(a,b)
上使用索引的速度几乎与单独在(a)
上使用索引的速度一样快。它不能单独使用(a,b)
上的索引,就好像它是(b)
上的索引一样-即使速度很慢,它也不能
至于DESC
条目,对于该页面,必须进行反向索引扫描,这比普通的正向索引扫描慢。如果您在EXPLAIN ANALYZE
中看到大量反向索引扫描,并且您可以负担额外索引的性能成本,则可以按DESC
顺序在字段上创建索引
这适用于WHERE
子句,而不仅仅是orderby
。您可以使用(a,b)
上的索引来搜索其中a=4
或其中a=4和b=3
,但不能单独搜索其中b=3
因此,我应该假设,与右边的列相比,基于最左边列的查找速度最快(我所说的列都是构成主键的列)?@AbhishekJain正确;使用PK最左边的列(或同时使用两列的查找)将使用索引,而仅使用PK最右边的列将根本无法使用索引。如果你需要在最右边的列上创建第二个索引,如果你不需要单独查找另一列的话,那么在最右边的列上创建第二个索引会很有帮助。@AbhishekJain不客气。我强烈建议您熟悉EXPLAIN ANALYZE
命令和psql
命令shell。这两种方法都可以帮助您更好地理解PostgreSQL的工作原理、分析查询的执行方式、测试不同的索引策略等。在尝试理解大型和复杂的查询计划时,它们也很有用。