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
不会改变结果集的场景。在实践中第二个查询更快吗?或者,如果提供了多个,数据库是否只使用一个最佳密钥?
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 或更早的版本中,导致至少有两个索引(施加额外的写入/维护/空间成本):
(primary_key)
,显然。UNIQUE
)索引(primary_key, something)
。Postgres的11加真正覆盖索引使用INCLUDE
条款,它方便地允许捎带非键列something
在PRIMARY 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
您提到的更宽的列(bigint
与int
示例中的类似不符合条件),您还可以搭载something
在 上的索引other_key
:
CREATE INDEX other_idx ON tbl(other_key) INCLUDE (something);
Run Code Online (Sandbox Code Playgroud)
虽然任一解决方案都可以优化给定查询的读取性能,但其他不检索的查询something
则必须使用更大的索引。所以权衡收益和成本(就像创建索引时一样)。
来自 Michael Paquier 的相关博客条目的详细信息: