Postgres:如何使用时间间隔在 timestamptz 上设置索引?

Postgres: How to setup an index on timestamptz using a time interval?

我有一个查询需要使用索引进行优化。有什么方法可以索引 timestamptz 类型的列 assigned_at 。我正在考虑使用 assigned_at 的 GIST 索引,有没有什么方法可以合并,因为我必须使用 now() 或传入可变且无法索引的当前日期时间。

select id from foo f where 
f.context_id =  
and (f.assigned_at <= (now() - interval '60 second') or f.assigned_at is null) 

打开以获取为此查询设置索引的建议!提前致谢!!

考虑到您发布的查询,使用 context_idassigned_at 的复合索引应该可以解决问题:

CREATE INDEX idx_foo ON foo (context_id,assigned_at);

根据您的数据,OR 条件可能会稍微减慢您的查询速度。另一种方法是将此条件拆分为两个不同的查询:

SELECT * FROM foo f 
WHERE f.context_id = 1 AND f.assigned_at <= (now() - interval '60 second')
UNION ALL
SELECT * FROM foo f WHERE f.context_id = 1 AND f.assigned_at IS NULL;

一如既往,尝试两种查询并测试哪种方法最适合您的数据。

演示:db<>fiddle

(context_id, assigned_at) 上的简单 btree 索引可用于该查询。但是要充分利用所有部分,需要读取索引两次并在它们之间做一个 BitmapOr。根据它认为每个术语的选择性,它可能会选择采用不同的方法,例如仅对 context_id 使用索引并将时间部分用作过滤器。

explain analyze select id from foo f where 
f.context_id = 7 
and (f.assigned_at <= (now() - interval '60 second') or f.assigned_at is null);
                                                                 QUERY PLAN                                                                  
---------------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on foo f  (cost=8.88..12.90 rows=1 width=4) (actual time=0.031..0.041 rows=7 loops=1)
   Recheck Cond: (((context_id = 7) AND (assigned_at <= (now() - '00:01:00'::interval))) OR ((context_id = 7) AND (assigned_at IS NULL)))
   Filter: ((assigned_at <= (now() - '00:01:00'::interval)) OR (assigned_at IS NULL))
   Heap Blocks: exact=4
   ->  BitmapOr  (cost=8.88..8.88 rows=1 width=0) (actual time=0.024..0.025 rows=0 loops=1)
         ->  Bitmap Index Scan on foo_context_id_assigned_at_idx  (cost=0.00..4.44 rows=1 width=0) (actual time=0.016..0.016 rows=0 loops=1)
               Index Cond: ((context_id = 7) AND (assigned_at <= (now() - '00:01:00'::interval)))
         ->  Bitmap Index Scan on foo_context_id_assigned_at_idx  (cost=0.00..4.43 rows=1 width=0) (actual time=0.007..0.007 rows=7 loops=1)
               Index Cond: ((context_id = 7) AND (assigned_at IS NULL))