具有主键和外键的查询是否比仅具有主键的查询运行得更快?

roc*_*oco 5 postgresql performance optimization query-performance

SELECT something FROM table WHERE primary_key = ?
Run Code Online (Sandbox Code Playgroud)

对比

SELECT something FROM table WHERE primary_key = ? AND other_key = ?
Run Code Online (Sandbox Code Playgroud)

假设这是一个包含other_key不会改变结果集的场景。在实践中第二个查询更快吗?或者,如果提供了多个,数据库是否只使用一个最佳密钥?

Erw*_*ter 5

询问

SELECT something FROM table WHERE primary_key = ?
Run Code Online (Sandbox Code Playgroud)

这是最快的形式。添加任何其他谓词只会使其变慢。理论上。

异国情调的例外适用,当PK指数臃肿出于某种原因,或者PK列是比较大的,或者多列PK,产生了更大的索引,而在添加谓词索引像other_key小。然后Postgres的可以决定使用索引所添加的谓词,访问堆和过滤器primary_key = ?。不太可能,但可能。

如果添加的谓词的计算结果为TRUE,则您不会得到任何行 - 不同的结果,因此不是一个公平的比较 - 但这不是您断言的情况。

一个FOREIGN KEY约束对读取性能没有直接影响。引用列甚至不必被索引(与被引用列相反)。

覆盖索引以获得最佳读取性能

随着非平凡规模的表,并没有太多的写活动,考虑增加一个多列索引(primary_key, something),允许仅索引扫描。在Postgres 10 或更早的版本中,导致至少有两个索引(施加额外的写入/维护/空间成本):

  1. PK 指数上(primary_key),显然。
  2. 上的普通(或冗余UNIQUE)索引(primary_key, something)

Postgres的11加真正覆盖索引使用INCLUDE条款,它方便地允许捎带非键列somethingPRIMARY KEY

CREATE TABLE tbl (
   primary_key bigint GENERATED ALWAYS AS IDENTITY
 , other_key   integer NOT NULL REFERENCES other_tbl
 , something   text
 , PRIMARY KEY (primary_key) INCLUDE (something)  -- here's the magic
);
Run Code Online (Sandbox Code Playgroud)

如果primary_key恰好是比other_key您提到的更宽的列(bigintint示例中的类似不符合条件),您还可以搭载something在 上的索引other_key

CREATE INDEX other_idx ON tbl(other_key) INCLUDE (something);
Run Code Online (Sandbox Code Playgroud)

虽然任一解决方案都可以优化给定查询的读取性能,但其他不检索的查询something则必须使用更大的索引。所以权衡收益和成本(就像创建索引时一样)。

来自 Michael Paquier 的相关博客条目的详细信息: