Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 具有复合主键的表中记录的顺序是什么_Postgresql_Sorting_Primary Key - Fatal编程技术网

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

Postgresql 具有复合主键的表中记录的顺序是什么,postgresql,sorting,primary-key,Postgresql,Sorting,Primary Key,在PostgreSQL中,当将多列的组合指定为主键时,记录是如何排序的 这是假设PostgreSQL按照主键的顺序对记录进行排序。是吗 此外,对于PostgreSQL,主键是否会自动索引?这个问题错误地假设主键会强制执行表顺序。没有。PostgreSQL表没有定义的顺序,有或没有主键;它们是一堆按页面块排列的行。如果需要,可以使用查询的ORDER BY子句进行排序 您可能认为PostgreSQL表是作为面向索引的表存储的,这些表以主键顺序存储在磁盘上,但Pg不是这样工作的。我认为InnoDB存储

在PostgreSQL中,当将多列的组合指定为主键时,记录是如何排序的

这是假设PostgreSQL按照主键的顺序对记录进行排序。是吗


此外,对于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的工作原理、分析查询的执行方式、测试不同的索引策略等。在尝试理解大型和复杂的查询计划时,它们也很有用。