Oracle:索引表的一部分行

Cli*_*ton 8 sql database oracle indexing

我有一个表有活动的非活动条目,活动= 1表示活动,活动= 0表示不活动.

我在这个表上有各种索引,但我只需要为活动条目维护索引,因为应用程序只查询活动数据.需要保留非活动数据,因为它可以再次变为活动状态,但这通常只能通过批量更新完成,无论如何都不会使用索引.

我注意到索引非活动条目(有越来越多的活动条目)占用相当多的空间.

Oracle(10g)中有没有办法做这样的事情:

create index an_idx on tab (active, col1, col2, ... , coln) where active = 1

以前的尝试:

我尝试使用基于函数的索引将第一列设置为null,active = 0如下所示:

create index an_idx on tab (decode(active, 1, 1, null), col1, col2, ... , coln)

但在这种情况下,Oracle似乎仍然会为非活动列编制索引.

Dav*_*sta 12

您的基本想法是正确的,但您需要将解码应用于所有列.只有当所有索引表达式NULL都未对该行进行索引时.

create index an_idx on tab (
  decode(active, 1, col1, null),
  ...
  decode(active, 1, coln, null)
)
Run Code Online (Sandbox Code Playgroud)

当然,如果您希望查询使用此索引,则必须在WHERE子句中使用相同的表达式.

注意我不认为您希望decode(active, 1, 1, null)在索引中包含表达式,因为它对于所有索引行都是常量.


Jon*_*ler 8

通过ACTIVE对表进行分区,创建本地索引,并使非活动分区的索引不可用.这将消除索引非活动数据所花费的时间.

create table tab(active number, col1 number, col2 number, col3 number)
    partition by list(active) 
    (partition tab_active values(1), partition tab_inactive values(0));

create index tab_index1 on tab(col1) local;

alter index tab_index1 modify partition tab_inactive unusable;
Run Code Online (Sandbox Code Playgroud)

但这种方法有一些潜在的缺点:

  • 并非所有类型的索引都不可用.
  • 在数据库中有不可用的对象是不正常的.人们可能会抱怨它或认为它是一个错误并重建它.
  • 某些操作(如truncate)将自动使索引再次可用.

在Oracle 12c中,您可以使用部分索引来完成此操作:

create table tab(active number, col1 number, col2 number, col3 number)
    partition by list(active) 
    (partition tab_active   values(1) indexing on,
     partition tab_inactive values(0) indexing off);

create index tab_index1 on tab(col1) local indexing partial;
Run Code Online (Sandbox Code Playgroud)