在实时数据库上更新之前删除索引

时间:2016-07-02 04:40:16

标签: django postgresql heroku-postgres

我们正在研究Heroku上的Postgres数据库。我们需要使用正则表达式替换多个字符串来更新大约500万行,这意味着可能总共执行大约1亿次更新。

我们正在以这种方式更新它:(使用psycopg2)

for element in list:
    cursor.execute("Update table set text = regexp_replace(text, %s, 'NewWord', 'gi') where date >= '2017-12-31';", [element])

数据库是实时的并且链接到我们的Django网站,我们需要在3天内推出一项新功能,要求对数据库进行此更新。 Postgres指南说,如果我们删除索引它会快得多,但删除外键索引可能会阻止我们的一些django功能并将网站关闭。即便如此,我们也可以在周末期间将这一方面减少一到两天,但仅此而已。

所以:

  1. 通过删除索引,可以安全地假设1亿 更新可以在一天内完成吗?
  2. 如果是,我们是否还应删除Primary 关键指标?
  3. 如果没有,我们假设有多少时间相似 更新将不删除索引吗?

1 个答案:

答案 0 :(得分:0)

  1. 可在一小时内完成1亿次更新。 (如果行大小不是太大)
  2. 否。主键不受更新文本字段的影响,因此您应该不管它
  3. 无论是否有索引,更新所需的时间大致相同(如果受影响的文本字段没有索引)
  4. 您的查询(为简单起见,我删除了参数化,并将{table,date,text}替换为{ztable,zdate,ztext},因为它是关键字):

    Update ztable
    set ztext = regexp_replace(ztext, 'Oldword', 'NewWord', 'gi')
    where zdate >= '2017-12-31';
    

    可以通过在where子句中添加额外条件来加速,例如:

    Update ztable
    set ztext = regexp_replace(ztext, 'Oldword', 'NewWord', 'gi')
    where zdate >= '2017-12-31'
    AND ztext LIKE '%Oldword%'
    ;
    

    如果更新实际上对行没有任何作用,这将避免创建额外的行版本。 (如果实际更改了行,则更新需要1个读取I / O +大约3个I / O,受影响的磁盘块数取决于sparsety和行大小)

    额外注意:如果ztext列上有索引:扔掉它;它可能没用。 通过删除前端的循环并将所有逻辑放在UPDATE中,可以获得额外的性能。