Oracle:索引表的一部分行

时间:2011-10-05 00:59:44

标签: sql database oracle indexing

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

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

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

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

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

以前的尝试:

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

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

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

3 个答案:

答案 0 :(得分:12)

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

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

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

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

答案 1 :(得分:8)

通过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;

答案 2 :(得分:1)

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

  1. 在(active,col1 ...)上创建索引,以便查询时间不受影响 非活动元素
  2. 为活动/非活动项目创建两个表,并通过在两个表之间移动来管理活动状态
  3. 创建第二个表,其中包含您要编制索引的所有数据以及唯一标识符,并加入表以获取其余数据。