在PostgreSQL索引中包含两次列
我正在构建一个基于PostgreSQL的工作队列,如上所述 我的队列定义与本文中描述的概念略有不同,它使用目标时间戳进行消费(在PostgreSQL索引中包含两次列,sql,postgresql,Sql,Postgresql,我正在构建一个基于PostgreSQL的工作队列,如上所述 我的队列定义与本文中描述的概念略有不同,它使用目标时间戳进行消费(due\u time): 只有一个索引: CREATE INDEX idx_publish_due_created ON publish_queue( due_time ASC NULLS FIRST, created ASC) WHERE(NOT is_complete); 让我们用测试数据集填充该表: begin transaction; INSERT INTO p
due\u time
):
只有一个索引:
CREATE INDEX idx_publish_due_created ON publish_queue(
due_time ASC NULLS FIRST, created ASC) WHERE(NOT is_complete);
让我们用测试数据集填充该表:
begin transaction;
INSERT INTO publish_queue(article_id, due_time)
SELECT 2407, t.day::date FROM generate_series(timestamp '2024-03-07', timestamp '2034-08-16',interval '1 minute') AS t(day);
commit;
并消费一件物品:
update publish_queue
set is_complete = true, completed = now()
where id = (
select id
from publish_queue
WHERE NOT is_complete AND (LOCALTIMESTAMP >= due_time OR due_time IS NULL)
order by due_time ASC NULLS FIRST, created ASC
for update skip locked
limit 1
)
returning article_id;
在我的系统上,查询需要约2秒钟才能完成,执行计划如下:
但是,如果我像下面这样更改索引,包括第二次更改到期时间,这是我以前从未做过的
CREATE INDEX idx_publish_due_created ON publish_queue(
due_time, due_time ASC NULLS FIRST, created ASC) WHERE(NOT is_complete);
查询耗时60毫秒,结果如下:
现在我的问题是,在索引中包含两次列感觉很奇怪。我是不是遗漏了什么?使用不同的索引或重新表述查询是否可以实现同样的效果?是的,这很奇怪。你可以做得更好:
CREATE INDEX ON (coalesce(due_time, '-infinity'::timestamp), created);
然后像这样查询:
SELECT id
FROM publish_queue
WHERE NOT is_complete
AND LOCALTIMESTAMP >= coalesce(due_time, '-infinity'::timestamp)
ORDER BY coalesce(due_time, '-infinity'::timestamp), created
FOR UPDATE SKIP LOCKED
LIMIT 1
如果只包含一次,而不先为
空
?@a_horse_,带有_no_名称,这就是它。为了让我接受你的评论,你能把它变成一个答案吗?一个没有名字的马的评论是正确的,但这也是有效的。
SELECT id
FROM publish_queue
WHERE NOT is_complete
AND LOCALTIMESTAMP >= coalesce(due_time, '-infinity'::timestamp)
ORDER BY coalesce(due_time, '-infinity'::timestamp), created
FOR UPDATE SKIP LOCKED
LIMIT 1