提取最近24小时内未更新的行

时间:2020-06-21 13:23:16

标签: postgresql

我有一个大表(40多个记录),其结构如下:

CREATE TABLE collected_data(
    id TEXT NOT NULL,
    status TEXT NOT NULL,
    PRIMARY KEY(id, status),
    blob JSONB,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);

我需要获取updated_at早于24小时且具有特定状态且blob不为空的所有(或至少100,000条)记录。

因此查询变为:

SELECT
    id
FROM
    collected_data
WHERE
    status = 'waiting'
    AND blob IS NOT NULL
    AND updated_at < NOW() - '24 hours'::interval
LIMIT 100000;

这将导致执行计划如下:

Limit  (cost=0.00..234040.07 rows=100000 width=12)
  ->  Seq Scan on collected_data  (cost=0.00..59236150.00 rows=25310265 width=12)
"        Filter: ((blob IS NOT NULL) AND (type = 'waiting'::text) AND (updated_at >= (now() - '24:00:00'::interval)))"

几乎总是导致全表扫描,这意味着某些查询确实很慢。

我试图创建像CREATE INDEX idx_special ON collected_data(status, updated_at);这样的索引,但这无济于事。

有什么办法可以使查询速度更快?

1 个答案:

答案 0 :(得分:1)

计划者认为25,310,265行将满足您的条件,因此认为通过seq扫描仅获取100,000个行,然后尽早停止将被破坏。如果实际上并没有那么多,或者有很多但它们都聚集在表的错误部分,那么实际上并不会那么快。如果在选择了100,000个之后,您下一步要做的是更新它们使其不再符合条件的方式,则可能是这种情况。因为那样的话,您必须不断走过去那些合格的残余物,才能找到下一批。

您可以通过在查询中添加“ order by Updated_at”来鼓励它使用索引。您还可以通过创建局部索引CREATE INDEX ON collected_data(status, updated_at) where blob is not nullCREATE INDEX ON collected_data(updated_at) where status='waiting' and blob is not null来堆叠甲板,以自己的喜好。