在PostgreSQL中的主键上缓慢加入

时间:2018-07-30 11:02:16

标签: postgresql

我在Windows 10上使用PostgreSQL 10.4,并且观察到了这种奇怪的缓慢性。

create table stock_prices (
    quote_date timestamp,
    security_id int NOT NULL,
    ...
    PRIMARY KEY (quote_date, security_id)
);
create index stock_prices_idx2 on stock_prices (security_id, quote_date);

立即执行以下操作。

select * from stock_prices where quote_date = '2017-12-29';

但是接下来的时间是31秒。

create temp table ts (
    quote_date timestamp,
    primary key (quote_date)
);

insert into ts values ('2017-12-29');

select p.* 
from stock_prices p, ts t
where p.quote_date = t.quote_date;

drop table ts;

AFAIK,上面应该点击索引。使用DBeaver的说明执行计划功能,它报告说它对stock_prices进行了“序列扫描”,我认为这意味着表扫描。

在我迁移到Postgres 10.4之前,我使用的SQL Server 2017 Developer Edition具有完全相同的架构,并且没有任何问题。该数据库的报价很大,因此我无法提供太多测试数据,但是基础数据直接来自沃顿商学院的WRDS学术研究数据库(我使用的表是CRSP.dsf)。知道为什么postgres不使用索引吗?

[编辑]好的,看起来很大程度上取决于Postgres认为临时表ts中的内容。在analyze ts;之前添加select使其瞬时。这很奇怪,但是无论如何...

2 个答案:

答案 0 :(得分:0)

quote_date表的ts列上还有一个主键/索引。由于您在此处进行内部联接,因此优化器应可以自由选择要在联接的左侧和右侧显示哪个表。假设将stock_prices表放在左侧,则可以利用ts.quote_date列上的索引。但是,在这种情况下,这意味着它将扫描stock_prices表。因此,当您切换Postgres的版本时,查询计划可能会更改,但是在这里我看不到任何意外情况。 Postgres没有使用您询问的索引,因为它似乎找到了更好的索引/表来使用。

答案 1 :(得分:0)

如上所述,添加analyze ts将解决此问题。看起来统计数据对Postgre计划查询的方式有很大的影响。