在添加列之前创建索引与在添加列之后创建索引 - 是否重要?

时间:2011-08-04 16:51:58

标签: oracle

在Oracle 10g中,创建索引和alter table的顺序是否重要?

假设我在表T中的C列上有一个带有where子句的查询Q.现在我执行以下方案之一:

  1. 我创建索引I(C),然后添加X,Y,Z列。
  2. 添加X,Y,Z列,然后创建索引I(C)。
  3. Q是'从T中选择*,其中C =任何'

    当T包含非常多的行时,在表1和2之间,Q的性能会有显着差异吗?

    我个人认为做#2是一种做法,但其他人似乎有不同意见。

    感谢

2 个答案:

答案 0 :(得分:4)

如果在创建索引之前或之后向表中添加列,则没有区别。优化器应为查询选择相同的计划,并且执行时间应保持不变。

根据表的物理存储参数,添加其他列并用数据填充它们可能会导致相当多的行迁移。该行迁移将生成对表上索引的更改。如果在使用数据填充三个新列时索引存在,则由于额外的索引维护,填充X,Y和Z中的数据可能会花费更长的时间。

答案 1 :(得分:1)

如果您添加列而不填充它们,那么它很快就会因为元数据更改而很快。添加索引确实需要读取表(或者可能是另一个索引),因此与记录新索引详细信息的简单元数据更改相比,这可能非常耗时且影响更大。

如果要将新列填充为ALTER TABLE的一部分,则另有不同之处。

  1. 在将数据添加到表格数据的每一行的过程中,数据库可能会发生计划外停机
  2. 服务器内存可能没有空间记录该表中更改的每一行
  3. 因此,这些行更改可能会在提交之前写入数据文件,因此会写为脏块
  4. 在ALTER表成功完成后,下一次读取这些块将执行延迟块清除(即记录已提交更改的事实)
  5. 如果首先添加列(带数据),那么create index将(可能)读取表并执行延迟块清除的附加工作。

    如果先创建索引然后添加列,则创建索引可能会更快但延迟块清除不会发生,并且稍后将由应用程序拾取内务处理(可能由select * from T where C = whatever