Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 重建索引时资源正忙_Sql_Oracle_Oracle10g_Indexing_Locking - Fatal编程技术网

Sql 重建索引时资源正忙

Sql 重建索引时资源正忙,sql,oracle,oracle10g,indexing,locking,Sql,Oracle,Oracle10g,Indexing,Locking,有一个表T,列a: CREATE TABLE T { id_t integer not null, text varchar2(100), a integer } / ALTER TABLE T ADD CONSTRAINT PK_T PRIMARY KEY (ID_T) / 索引是这样创建的: CREATE INDEX IDX_T$A ON T(a); 还有这样一个检查约束: ALTER TABLE T ADD CONSTRAINT CHECK (a is null or

有一个表
T
,列
a

CREATE TABLE T {
  id_t integer not null,
  text varchar2(100),
  a integer
} 
/

ALTER TABLE T ADD CONSTRAINT PK_T PRIMARY KEY (ID_T)
/
索引是这样创建的:

CREATE INDEX IDX_T$A ON T(a);
还有这样一个检查约束:

ALTER TABLE T ADD CONSTRAINT CHECK (a is null or a = 1);
T
中的大多数记录都有空值
a
,因此,如果索引处于一致状态且其统计信息是最新的,则使用索引的查询速度非常快

但是问题是一些行的
a
的值变化非常频繁(一些行得到null值,一些行得到1),我需要重建索引,比如说每小时一次

但是,当作业执行此操作时,尝试重建索引时,通常会出现异常:

ORA-00054: resource busy and acquire with NOWAIT specified
有人能帮我解决这个问题吗?

你有没有试过在索引重建语句中添加“ONLINE”

编辑:如果联机重建不可用,则可以查看提交实体化视图上的快速刷新,以存储列a为1的行的rowid或主键

首先看一下文档:-

您将在表上创建一个实体化视图日志,然后创建一个实体化视图


请特别考虑这方面的资源需求:对主表的更改需要将更改向量写入Materialized view log,这实际上是每个更改的附加插入。然后,必须使用其他查询将更改传播到另一个表(已实现的视图存储表)。这绝不是一个低影响的选项。

由于所讨论的字段的基数非常低,我建议使用位图索引并完全跳过重建

CREATE BITMAP INDEX IDX_T$A ON T(a);

注意(如注释中所述):位图索引的事务性能非常低,因此只有在很少重叠事务对表进行更新的情况下,这种方法才能很好地工作

大多数情况下不需要重建索引。当然,新创建的索引是有效的,它们的效率会随着时间的推移而降低。但这一过程在一段时间后停止——它只是收敛到某种程度

如果您确实需要优化索引,请尝试使用侵入性较小的DDL命令“ALTERINDEX SHRINK SPACE COMPACT”


PS:我还建议您为表空间存储使用一些较小的块大小(4K或8K)

重建性能

大多数Oracle专家对频繁重建索引表示怀疑。例如,快速浏览一下演示文稿,就会发现索引的行为并不像许多人想象的那样幼稚

该演示文稿中的一个相关要点是“完全删除的块被回收,通常不会有问题”。如果您的值完全改变,那么您的索引不应该无限大。虽然索引的使用方式不典型,但是 行为可能是一件好事

这里有一个简单的例子。创建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
重建统计数据

担心数据变化如此剧烈的对象的统计数据是件好事。但同样,尽管您的系统与众不同,但它可以与默认的Oracle行为配合使用。虽然索引的行可能会完全改变,但相关的统计数据可能保持不变。如果始终有100行索引,则行数、块数和区分度将保持不变

--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
如果100行从完全随机变为彼此非常接近,那么聚类因子可能会发生显著变化。但即使这样也可能无关紧要。如果有数百万行,但只有100行被索引,那么不管聚类因子如何,优化器的决策可能都是相同的。读取1个块(可怕的聚类因子)或读取100个块(最坏的聚类因子)看起来仍然比对数百万行进行全表扫描要好得多

但统计数据是复杂的,我肯定过于简化了。如果需要以特定的方式保存统计数据,则可能需要锁定它们。不幸的是,不能只锁定索引,但可以锁定表及其依赖索引

begin
    dbms_stats.lock_table_stats(ownname => user, tabname => 'T');
end;
/
无论如何都要重建

如果仍然需要重建,@Robe Eleckers重试的想法应该会奏效。虽然它不是一个异常,但更容易设置


会话仍然需要获得表上的独占锁,但这将使找到正确的机会窗口变得更加容易。

您可以通过重试机制来处理它。捕获资源繁忙异常并重试,直到成功。快速更改对索引有什么影响,导致需要频繁重建?有关它的统计信息很快过期。重新编译regathers统计信息并使索引更小(读取对它的查询会更快)。联机重建是我无法使用的企业选项。您能否提供一个示例,说明Materialized视图的含义?它看起来真的很不错。如果多个会话中的值变化很快,那么这对并发性来说就相当糟糕了,尽管如此。如果数据通过多个进程同时更改且非常频繁,则可以使用位图索引。顺便说一句,
select*from v$option,其中parameter='Bit-mapped index'
表示它在standart edition中也不可用。想象一下,当表中有数百万行,而只有一百行时的情况没有索引列的not null值,一小时后not null值有绝对不同的行(以前的行中有null),您确定索引不会继续永久增长并变得越来越低效率吗?Oracle索引正在进行自我碎片整理。至少在某种程度上。它还取决于列索引的顺序。如果某个索引不适合您的搜索需求,请查找“星型设计模式”——它用于数据仓库系统。这很简单。或者还有一个选项“压缩”索引。还有一个注释,索引“大小”可以表达给我们
begin
    dbms_stats.lock_table_stats(ownname => user, tabname => 'T');
end;
/
alter session set ddl_lock_timeout = 500;