在用数据填充表格之前或在数据到位之后创build索引是否更好?

我有一个大约100M行的表格,我将要复制来改变,添加一个索引。 我不太关心创build新表所需的时间,但是如果在插入任何数据或先插入数据然后添加索引之前更改表,那创build的索引会更有效率吗?

在数据插入之后创build索引是更有效的方法(甚至经常build议在批量导入之前和导入之后重新创build时删除索引)。

Syntetic示例(PostgreSQL 9.1,慢速开发机器,100万行):

CREATE TABLE test1(id serial, x integer); INSERT INTO test1(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id); -- Time: 7816.561 ms CREATE INDEX test1_x ON test1 (x); -- Time: 4183.614 ms 

插入,然后创build索引 – 约12秒

 CREATE TABLE test2(id serial, x integer); CREATE INDEX test2_x ON test2 (x); -- Time: 2.315 ms INSERT INTO test2(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id); -- Time: 25399.460 ms 

创build索引,然后插入 – 约25.5秒(慢两倍以上)

在添加行之后创build索引可能会更好。 不仅会更快,但树木平衡可能会更好。

编辑 “平衡”可能不是这里最好的select。 在b-tree的情况下,其定义是平衡的。 但是这并不意味着b-tree具有最佳的布局。 父节点内的子节点分布可能不均衡(导致未来更新中的成本更高),如果在更新过程中没有仔细执行平衡,树深度可能会超过必要的深度。 如果索引是在添加行之后创build的,则更有可能具有更好的分布。 此外,build立索引后,磁盘上的索引页可能会有较less的碎片。 这里有更多的信息

这个问题并不重要,因为:

  1. 如果您先将数据添加到表中,然后添加索引。 您的索引生成时间将是O(n*log(N))更长(其中n是添加的行)。 因为树的生成时间是O(N*log(N))那么如果将它分解成旧数据和新数据,得到O((X+n)*log(N))这可以简单地转换为O(X*log(N) + n*log(N))并以这种格式,你可以简单地看到你会等待额外的东西。
  2. 如果你添加索引,并把数据之后。 每增加一行(你有n新行),你会得到更长的时间插入额外的时间O(log(N)) ,在添加新元素后重新生成树的结构(索引列从新行开始,因为索引已经存在,那么索引必须重新生成为平衡结构,这个成本O(log(P))其中P是索引功率[指数中的元素] )。 你有n新行,最后你有n * O(log(N))然后O(n*log(N))总结额外的时间。

在大多数情况下创build的索引要快得多。 案例:varchar(255) – (商业名称)上的全文2000万行索引在导入行的同时 – 最差的情况下最多需要20秒的匹配。 删除索引并重新创build – 匹配每次less于1秒

我不确定这对于索引效率是否真的很重要,因为在这两种情况下,您都将新数据插入到索引中。 基本上,服务器不知道一个索引在构build之后会有多不平衡。 速度明智,显然,做插入没有索引。