Oracle更改索引以允许对空值进行索引

Dre*_*mer 5 sql oracle indexing

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

select count(*) from huge_table where half_null_col is null;
Run Code Online (Sandbox Code Playgroud)

即使已经编入索引,也将是一场性能灾难:

create index half_null_col_idx on huge_table(half_null_col asc);
Run Code Online (Sandbox Code Playgroud)

有两个问题:

  1. Oracle 11g应该支持一个常量表达式来索引空值,但很抱歉我通过了oracle doc但是找不到关于它的明确的官方文档.如果有人知道,请分享参考

  2. 如何改变指数代替drop,并create再次以避免出现性能问题.

nop*_*svk 7

你现在至少有四种选择:

  1. 创建"常量表达式"索引......

    create index half_null_col_idx
    on huge_table (half_null_col, 1);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在表上创建位图索引.位图索引也允许索引NULL ...

    create bitmap index half_null_col_idx
    on huge_table (half_null_col);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在基于函数的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>'
    ;
    
    Run Code Online (Sandbox Code Playgroud)
  4. 重新分区表,以便将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;
    
    Run Code Online (Sandbox Code Playgroud)

如果只count(*)从表中选择,那么位图索引可能是您的最佳选择.

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

如果你不能/不想重新分区表而你不能创建位图索引(例如,由于表上的并发DML活动很多),那么"常量表达式"索引或"NULL重新映射" "对某事"索引可能是你最好的选择.


要回答您的原始问题:

  1. Oracle内部将其视为"基于功能的索引".或许可以搜索这个术语.
  2. 你不能.但是,在线索引下降+创建afaik没有相关的性能开销.Oracle DB足以在这里处理"多任务处理"的事情 - 创建索引以及您的应用程序几乎像以前一样快速地工作.如果您需要重新创建索引,请执行此操作.如果你选择"常量表达式"选项,你可以先创建新索引,然后删除旧索引.