【问题标题】:Postgresql update query taking too long to complete every timePostgresql 更新查询每次都花费太长时间才能完成
【发布时间】:2021-02-28 15:32:32
【问题描述】:

我的 PostgreSQL 数据库表 user_book_details 有 451007 条记录。 user_book_details 表每天都在填充大约 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 列上没有索引。

【问题讨论】:

    标签: sql postgresql indexing sql-update dml


    【解决方案1】:

    您的查询没问题:

    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;
    

    这可能比尝试在表中保持最新更可取。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-04
      • 2020-01-31
      • 1970-01-01
      • 1970-01-01
      • 2018-11-26
      • 1970-01-01
      • 1970-01-01
      • 2022-12-23
      相关资源
      最近更新 更多