不幸的是,巨大表的一列只有一半的数据为空,因此在查询时

select count(*) from huge_table where half_null_col is null;

即使已经被索引,也将是性能的灾难:
create index half_null_col_idx on huge_table(half_null_col asc);

有两个问题:
  • Oracle 11g应该是support a constant expression to index on null values,但是很抱歉,我阅读了oracle doc,但是找不到有关它的明确官方文档。如果有人知道
  • ,请分享引用
  • 如何再次更改索引而不是dropcreate以避免性能问题。
  • 最佳答案

    目前,您至少要想到四个选择:

  • 创建“常量表达式”索引...
    create index half_null_col_idx
    on huge_table (half_null_col, 1);
    
  • 在表上创建一个位图索引。位图索引也允许索引NULL ...
    create bitmap index half_null_col_idx
    on huge_table (half_null_col);
    
  • 在基于函数的NULL重映射到某物的值上创建索引,并在查询中使用该重映射的NULL而不是查询NULL。
    create index half_null_col_idx
    on huge_table (nvl(half_null_col, '<a value that does not appear in the values of the column>'));
    
    select *
    from huge_table
    where nvl(half_null_col, '<a value that does not appear in the values of the column>')
        = '<a value that does not appear in the values of the column>'
    ;
    
  • 重新分区表,以使NULL值全部进入一个分区,其余值进入不同的分区。
    create table huge_table_2
    partition by list (half_null_col)
    (
        partition pt_nulls values (null),
        partition pt_others values (default)
    )
    as
    select *
    from huge_table;
    


  • 如果仅从表中选择count(*),则位图索引可能是最佳选择。

    如果要使用其他地方的表中的完整数据行(在联接到另一个表中或将其导出为CSV或其他格式),那么重新分区可能是最佳选择。

    如果您不能/不想对表进行重新分区并且不能创建位图索引(例如,由于表上大量并发DML事件),则使用“常量表达式”索引或“重新映射NULL” -to-something”索引可能是您的最佳选择。

    要回答您的原始问题:
  • Oracle在内部将它们作为“基于函数的索引”进行处理。也许搜索这个词。
  • 您不能。但是,在线索引drop + create afaik没有相关的性能开销。 Oracle DB足以胜任这里的“多任务”工作-创建索引以及与应用程序一样的运行,几乎可以像以前一样快。如果您需要重新创建索引,请执行此操作。而且,如果您使用“常量表达式”选项,则可以先创建新索引,然后再删除旧索引。
  • 10-05 22:50
    查看更多