点击上方“
CSDN
”,选择“置顶公众号”
关键时刻,第一时间送达!
作者丨Craig Kerstiens
译者
丨
夜风轻扬
译者注:
在Postgres中进行数据库迁移时会遇到哪些问题?如何解决它们?请见下文。
随着数据库的增长与扩展,你需要对一些操作给予更多的关注。你可能没有完全意识到,在开发环境中执行应用程序时,执行某些操作的成本,与在生产环境中大相径庭。在某一时刻,我们中的大多数人都犯了错,在5分钟时开始运行一些迁移,过15分钟仍然在运行,突然间生产流量受到了影响。
有两种操作发生的很频繁,每种操作都有一些简单的方法可以减少停机时间。让我们看看每一个操作,它们是如何工作的,以及如何以更安全的方式来处理它们。
添加新列
在Postgres中添加一个新列实际上代价是很低的。当你这样做的时候,它会更新对于已有列时刻的跟踪,它几乎是瞬时的。当对某个列有一些约束时,这一部分就会变得很昂贵。一个约束可以是一个主键或者外键,或者是一些唯一性约束。 Postgres不得不扫描表中的所有记录以确保没有违反这些约束。添加诸如“非空”等一些约束时,可能会有一些违反,但这不是最常见的原因。
造成添加新列迟缓最常见的原因是大部分的框架中为新列设置缺省值太过简单。对于所有的新记录这是一回事,但是对于已有的表来说,这意味着数据库不得不要读取所有的记录并且向这些记录中重写新的缺省值。对于只有几百条记录的表来说,这还不算太糟,但是对于上千万条记录的表来说,这时间就无法容忍了 。
简而言之,在添加新列时,如果将其设为非空或者在创建是设置一个缺省值都会给你带来麻烦。解决之道是不要这样做。但是,如果你需要一个缺省值或者不想字段为空时该怎么办。这有一些你可以采取的简单步骤,将你的迁移工作从一步分为 四步:
1. 添加新列,允许其为空
2. 开始在所有新记录和更新中写入默认值
3. 逐步回填缺省值
4. 应用你的约束
是的,只是稍微多一点工作,对现有工作的影响很微小。
索引
类似大部分的DDL操作,创建索引时会加锁,这就意味着所有新的数据必须等待索引创建完成后才可以写入。对于新建的或者小规模的表,等待的时间不是很明显,但是对于大规模数据库,等待的时间可能是以分钟甚至小时计添加索引的本意是为了提高查询速度,但是实际的效果却是降低了速度,这真是有点讽刺。
Postgres中对于这个问题的答案是 CONCURRENT 创建索引。就是在后台逐步创建索引。你可以通过:CREATE INDEX CONCURRENTLY语句并发创建索引。一旦创建了索引,只要你做想做的事情,Postgres就会在查询中使用它。