2010-09-10 24 views

回答

70

创建索引是更有效的方式(它甚至常常recomended批量导入前,后的进口重新它删除索引)。

Syntetic示例(PostgreSQL的9.1,缓慢发展的机器,一个百万行):

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 

插入,然后创建索引 - 约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 

创建索引,然后插入 - 约25.5秒(超过两倍慢)

+3

+1,索引将显着减慢涉及100M行插入任务的操作,因此最好放弃它们并重新创建它们。 – code4life 2010-09-10 23:29:54

7

这可能是更好的添加行后创建索引。不仅会更快,但树木平衡可能会更好。

编辑“平衡”可能是不是在这里术语的最佳选择。在b-tree的情况下,其定义是平衡的。但这并不意味着b-tree具有最佳布局。父节点内的子节点分布可能不均匀(导致未来更新中的成本更高),并且如果在更新过程中未谨慎执行平衡,树深度可能会超过必要的深度。如果在添加行之后创建索引,则更有可能具有更好的分布。另外,索引建立后,磁盘上的索引页可能会有较少的碎片。数据插入后A bit more information here

1

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

  1. 如果您先将数据添加到表中,然后再添加索引。您的索引生成时间将会延长O(n*log(N))(其中n是添加的行)。由于树gerating时间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))总结额外的时间。
-1

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

0

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

相关问题