【发布时间】:2021-10-14 10:32:02
【问题描述】:
我在 PostgreSQL 13 中有这张表:
CREATE TABLE candles (
id serial primary key,
day integer,
minute integer,
"open" integer,
high integer,
low integer,
"close" integer,
volume integer,
id_d1 integer,
);
CREATE INDEX candles_idx1 ON public.candles (day,minute);
我尝试更新字段id_d1,它应该在同一时间包含前一天的id:
UPDATE candles s2
SET id_d1 = (SELECT id FROM candles s
WHERE s.id<s2.id
AND s.day<s2.day
AND s.minute=s2.minute
ORDER BY s.id DESC
LIMIT 1);
对于较小的数据量,它运行良好。对于 80k 条记录,它会无休止地运行。
解释查询:
Update on candles s2 (cost=0.00..744027.57 rows=80240 width=68)
-> Seq Scan on candles s2 (cost=0.00..744027.57 rows=80240 width=68)
SubPlan 1
-> Limit (cost=0.29..9.25 rows=1 width=4)
-> Index Scan Backward using candles_pkey on candles s (cost=0.29..2347.34 rows=262 width=4)
Index Cond: (id < s2.id)
Filter: ((day < s2.day) AND (minute = s2.minute))
我也试过(WHERE 子句中没有 id):
EXPLAIN
UPDATE candles s2
SET id_d1 = (SELECT id FROM candles s
WHERE s.day<s2.day
AND s.minute=s2.minute
ORDER BY s.id DESC
LIMIT 1);
结果:
Update on candles s2 (cost=0.00..513040.75 rows=80240 width=68)
-> Seq Scan on candles s2 (cost=0.00..513040.75 rows=80240 width=68)
SubPlan 1
-> Limit (cost=0.29..6.37 rows=1 width=4)
-> Index Scan Backward using candles_pkey on candles s (cost=0.29..4784.85 rows=787 width=4)
Filter: ((day < s2.day) AND (minute = s2.minute))
我应该如何修改查询或架构以在合理的时间内运行它?
【问题讨论】:
-
您需要
id列吗?从功能上讲,您的主键似乎是(day,minute)- 为什么不坚持使用它,然后使用视图来实现day, day-1配对?
标签: sql postgresql sql-update greatest-n-per-group postgresql-13