索引中的碎片如何发生?

时间:2018-07-04 18:10:42

标签: postgresql memory indexing fragmentation

我有一个200GB的表,索引为49GB。该表仅发生插入和更新操作。我删除了现有索引,并在同一列上创建了一个新索引。新索引大小仅为6GB。我正在使用postgres数据库

有人可以解释如何将索引大小从50GB减少到6GB吗?

1 个答案:

答案 0 :(得分:3)

新创建的索引实质上是最佳打包的排序数据。要在中间放置一些数据,同时又要保持最佳的打包排序数据,则平均每次插入都要重写一半的索引。

这是不可接受的,因此数据库对索引使用了一些复杂且聪明的格式(基于b树数据结构),该格式允许更改索引块的顺序而不将其移动到磁盘上。但是这样做的结果是,在中间插入一些数据后,某些索引数据块并未100%打包。剩下的空间可以在将来使用,但前提是插入的值在顺序方面与块匹配。

因此,根据您的使用方式,您可以轻松地将索引块平均仅打包10%。

以下事实更加复杂:在更新一行时,旧版本和新版本都必须同时存在于索引中。而且,如果对整个表进行批量更新,则索引必须扩展为包含两倍的行数,尽管只是短暂的。但这不会轻易缩小,因为这基本上需要全部重写。

索引大小倾向于先增长,然后在使用后稳定下来。但是稳定的大小通常远不及新创建的大小。

您可能希望调整自动真空度,使其更具侵略性-因此,表和索引中不再需要的空间会更快地恢复,因此可以更快地重用。这可以使索引稳定得更快,更小。另外,请尝试避免进行过多的批量更新,或者在进行大规模更新后执行vacuum full tablename