postgres怎么在线创建索引
我们知道数据库创建索引可能会锁住创建索引的表,并且用该表上的一次扫描来执行整个索引的构建,这样在创建索引时会影响在线业务,非常大的表创建索引可能会需要几个小时,这样阻塞业务是不被允许的。商业数据库一般都提供在线创建索引的能力,PostgreSQL作为开源数据库,也提供了这样的功能。我们在CREATE INDEX命令中新增CONCURRENTLY选项来实现索引的在线创建。 但是concurrently在线创建索引也并不是那么完美,当使用这个选项时,PostgreSQL必须执行该表的两次扫描,此外它必须等待所有现有可能会修改或者使用该索引的事务终止,甚至它可能会等待一个不相干的事务终止。因此这种方法比起普通的索引创建过程来说要做更多工作并且需要更多时间。同时,索引的创建会带来较大的CPU和I/O消耗。甚至在极端情况下,如果数据库存在长事务,我们发现create index命令根本无法结束。 从官方文档中我们可以了解到如下信息,在并发(concurrently)索引构建中,索引实际上是在事务中被构建的,它在两个事务中发生两次表扫描。在每一次表扫描之前,索引构建必须等待对该表做过修改的现有事务终止。在第二次扫描之后,索引构建必须等待任何持有早于第二次扫描的快照的事务终止。然后该索引最终能被标记为可用,CREATE INDEX命令完成。
开启第一个事务,拿到当前快照snapshot
2.等待所有修改过该表的事务结束
3.扫描该表,第一次创建索引
4.结束第一个事务
5.开启第二个事务,拿到当前快照snapshot2
6.等待所有修改过该表的事务结束
7.第二次扫描该表,将两次快照之间变更的记录,合并到索引
8.上一步更新索引结束后,等待snapshot2之前开启的所有事务结束
9.结束索引创建,索引变为可用 那么这里有个疑问,为什么需要两次扫描、两次创建索引?其实想想也很好解释。因为在第一次创建索引的时候不阻塞读写,这段时间内发生的变更需要在第二次扫描的时候合并更新进索引。