Postgresql 更新查询每次都需要很长时间才能完成
Postgresql update query taking too long to complete every time
我的 PostgreSQL 数据库 table user_book_details 有 451007 条记录。 user_book_details table 每天都有大约 1K 条新记录。
我有以下查询,每次都需要很长时间(13 小时)才能完成。
update user_book_details as A1 set min_date=
(select min(A2.acc_date) as min_date from user_book_details A2 where A2.user_id=A1.user_id
and A2.book_id=A1.book_id) where A1.min_date is null;
如何重写查询以提高性能?
仅供参考,user_id 和 book_id 列没有索引。
您的查询没问题:
update user_book_details ubd
set min_date = (select min(ubd2.acc_date)
from user_book_details ubd2
where ubd2.user_id = ubd.user_id and
ubd2.book_id = ubd.book_id
)
where ubd.min_date is null;
为了性能,您需要 user_book_details(user_id, book_id)
上的索引。我也觉得这样写会更快:
update user_book_details ubd
set min_date = min_acc_date
from (select ubd2.user_id, ubd2.book_id, min(ubd2.acc_date) as min_acc_date
from user_book_details ubd2
group by ubd2.user_id, ubd2.book_id
) ubd2
where ubd2.user_id = ubd.user_id and
ubd2.book_id = ubd.book_id and
ubd.min_date is null;
第一种方法使用索引来查找每行的值(更新相同查询时可能会有点复杂)。第二种方法聚合数据,然后加入值。
我应该注意到这个值很容易即时计算:
select ubd.*,
min(acc_date) over (partition by user_id, book_id) as min_acc_date
from user_book_details ubd;
这可能比尝试在 table 中保持最新更可取。
我的 PostgreSQL 数据库 table user_book_details 有 451007 条记录。 user_book_details table 每天都有大约 1K 条新记录。
我有以下查询,每次都需要很长时间(13 小时)才能完成。
update user_book_details as A1 set min_date=
(select min(A2.acc_date) as min_date from user_book_details A2 where A2.user_id=A1.user_id
and A2.book_id=A1.book_id) where A1.min_date is null;
如何重写查询以提高性能? 仅供参考,user_id 和 book_id 列没有索引。
您的查询没问题:
update user_book_details ubd
set min_date = (select min(ubd2.acc_date)
from user_book_details ubd2
where ubd2.user_id = ubd.user_id and
ubd2.book_id = ubd.book_id
)
where ubd.min_date is null;
为了性能,您需要 user_book_details(user_id, book_id)
上的索引。我也觉得这样写会更快:
update user_book_details ubd
set min_date = min_acc_date
from (select ubd2.user_id, ubd2.book_id, min(ubd2.acc_date) as min_acc_date
from user_book_details ubd2
group by ubd2.user_id, ubd2.book_id
) ubd2
where ubd2.user_id = ubd.user_id and
ubd2.book_id = ubd.book_id and
ubd.min_date is null;
第一种方法使用索引来查找每行的值(更新相同查询时可能会有点复杂)。第二种方法聚合数据,然后加入值。
我应该注意到这个值很容易即时计算:
select ubd.*,
min(acc_date) over (partition by user_id, book_id) as min_acc_date
from user_book_details ubd;
这可能比尝试在 table 中保持最新更可取。