重建性能
大多数 Oracle 专家对频繁重建索引持怀疑态度。例如,快速浏览一下Rebuilding the Truth演示文稿,您会发现索引的行为方式并不像许多人认为的那样天真。
该演示文稿中的相关要点之一是“完全删除的块被回收并且通常没有问题”。如果您的值完全改变,那么您的索引不应无限增长。尽管您的索引以非典型方式使用,但这种行为可能是一件好事。
这是一个简单的例子。创建 100 万行并索引其中的 100 个。
--Create table, constraints, and index.
CREATE TABLE T
(
id_t integer primary key,
text varchar2(100),
a integer check (a is null or a = 1)
);
CREATE INDEX IDX_T$A ON T(a);
--Insert 1M rows, with 100 "1"s.
insert into t
select level, level, case when mod(level, 10000) = 0 then 1 else null end
from dual connect by level <= 1000000;
commit;
--Initial sizes:
select segment_name, bytes/1024/1024 MB
from dba_segments
where segment_name in ('T', 'IDX_T$A');
SEGMENT_NAME MB
T 19
IDX_T$A 0.0625
现在完全洗牌大约 1000 次索引行。
--Move the 1s around 1000 times. Takes about 6 minutes.
begin
for i in 9000 .. 10000 loop
update t
set a = case when mod(id_t, i) = 0 then 1 else null end
--Don't update if the vlaue is the same
where nvl(a,-1) <> nvl(case when mod(id_t,i) = 0 then 1 else null end,-1);
commit;
end loop;
end;
/
索引段大小仍然相同。
--The the index size is the same.
select segment_name, bytes/1024/1024 MB
from dba_segments
where segment_name in ('T', 'IDX_T$A');
SEGMENT_NAME MB
T 19
IDX_T$A 0.0625
重建统计
担心数据变化如此剧烈的对象的统计数据是件好事。但同样,尽管您的系统不寻常,但它可能在默认的 Oracle 行为下正常工作。尽管索引的行可能会完全改变,但相关的统计数据可能保持不变。如果始终有 100 行索引,则行数、块数和不同性将保持不变。
如果 100 行从完全随机变为彼此非常接近,那么聚类因子可能会发生显着变化。但即使这样也可能无关紧要。如果有数百万行,但只有 100 个索引,则优化器的决策可能是相同的,而不管集群因素如何。读取 1 个块(极好的聚类因子)或读取 100 个块(最坏情况的聚类因子)看起来仍然比对数百万行进行全表扫描要好得多。
但是统计数据很复杂,我肯定是过度简化了事情。如果您需要以特定方式保存统计信息,您可能需要锁定它们。不幸的是,你不能只锁定一个索引,但你可以锁定表和它的依赖索引。
begin
dbms_stats.lock_table_stats(ownname => user, tabname => 'T');
end;
/
无论如何都要重建
如果仍然需要重建,@Robe Eleckers 重试的想法应该可行。尽管设置DDL_LOCK_TIMEOUT会更容易,而不是异常。
alter session set ddl_lock_timeout = 500;
会话仍然需要在表上获得排他锁,但这将使找到正确的机会窗口变得更加容易。