时间戳与当前时间的部分索引

时间:2017-02-27 14:01:23

标签: postgresql indexing timestamp query-optimization partial-index

我有一个查询,我通过比较五个月前的插入时间戳来过滤行。

此字段未更新,如果有帮助,我们可能会认为它是不可变的。

CREATE TABLE events (
    id serial PRIMARY KEY,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL
);

SELECT *
FROM events e
WHERE e.inserted_at >= (now() - '5 minutes'::interval);

EXPLAIN ANALYZE VERBOSE

Seq Scan on public.events e  (cost=0.00..459.00 rows=57 width=12) (actual time=0.738..33.127 rows=56 loops=1)
    Output: id, inserted_at
    Filter: (e.inserted_at >= (now() - '5 minutes'::interval))
    Rows Removed by Filter: 19944
Planning time: 0.156 ms
Execution time: 33.180 ms

似乎PostgreSQL在该字段上执行序列扫描,这会增加代价。

我是否有机会创建B树部分索引,或者其他任何内容来优化该查询?

1 个答案:

答案 0 :(得分:2)

过去5分钟的部分索引每隔一段时间就需要重建一次。您可以与cron同时构建它(当你关系密集使用时),删除旧索引。这样的方法当然可以让你更快地选择最后插入的数据,但考虑到至少每5分钟你必须重新扫描表来构建短的部分索引。

解决方法是数学 - 您可以分阶段拆分索引构建(作为函数):

select now()- inserted_at >= '5 minutes'::interval
from events 
where id > (currval('events_id_seq') - 5*(1000000/30))

得到的id低于最后一个id值减去最近5分钟插入的近似值。

如果结果为true,则在动态查询中使用相同的数学构建索引,否则,放大步骤。

这样你只扫描PK来建立时间戳索引 - 会便宜得多。

另一点 - 如果你应用这样的计算,你可能根本不需要部分索引?..