2011-10-05 45 views
7

我有一个表有活动的非活动条目,active = 1 for active和active = 0 for inactive。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)

但甲骨文似乎仍指数无效列在这种情况下。

回答

7

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

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; 

但也有一些潜在的不利因素,以这种方式:

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

在Oracle 12c中,你可以使用partial indexes做到这一点:

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; 
1

我不认为这是可能的。有几个选项

  1. 制作上,这样的查询时间不受不活跃因素的影响 尽可能多
  2. 为有效/无效项目创建两个表和管理(活动中,col1 ...)的索引通过在两个表格之间移动东西来激活状态
  3. 创建一个包含所有需要索引的数据的第二个表格以及一个唯一标识符并加入表格以获取其余数据。
+0

如果节省空间,是你的目标,选择2将使意义IMO。 –

11

您的基本想法是正确的,但您需要将解码应用于所有列。只有当所有索引表达式都是NULL时,行才会被索引。

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

当然,如果你再要查询中使用这个指标,它必须使用相同的表达式WHERE子句。

注意我不认为你想在表中包含decode(active, 1, 1, null)这个表达式,因为它对于所有索引行都是不变的。

+0

感谢您的解决方案。我担心我不得不做这样的事情。认为可能有更清洁的东西。 – Clinton