仅为特定值创建索引

And*_*rás 2 performance index oracle query-performance

我们有一个非常频繁调用的查询,所以我想提高性能,但有些同事担心索引的大小及其对插入更新的影响。

SELECT field1, field2 
  FROM table1 
  WHERE field3 = '101'
  AND   field2 = @variable
Run Code Online (Sandbox Code Playgroud)

table1有大约 500 万行,但只有大约 2000 行有field3 = 101.

 CREATE TABLE table1 (
   field1 varchar
   field2 int
   field3 int);
Run Code Online (Sandbox Code Playgroud)

是否可以仅为 oracle 11g 中的这 2000 行创建和索引 (field2, field1)?
我该怎么做?

Dav*_*itz 5

数据库 SQL 语言参考 - CREATE INDEX

“除了位图索引之外,Oracle 不会索引所有键列都为空的表行。”

演示

create table t as select level as field3 from dual connect by level <= 1000000;
alter table t add field3_ind as (case when field3 = 101 then field3 end);
create index t_ix_field3_ind on t (field3_ind); 
Run Code Online (Sandbox Code Playgroud)
select * from t where field3_ind = 101;
Run Code Online (Sandbox Code Playgroud)

执行计划


select    segment_name
         ,segment_type
         ,bytes

from      dba_segments 

where     owner        =  'DMARKOVITZ' 
      and segment_name in ('T','T_IX_FIELD3_IND')

order by  segment_name             
;
Run Code Online (Sandbox Code Playgroud)
+-----------------+--------------+----------+
| SEGMENT_NAME    | SEGMENT_TYPE | BYTES    |
+-----------------+--------------+----------+
| T               | TABLE        | 13631488 |
+-----------------+--------------+----------+
| T_IX_FIELD3_IND | INDEX        | 65536    |
+-----------------+--------------+----------+
Run Code Online (Sandbox Code Playgroud)

Ps
虚拟列的使用使得查询更加人性化。

如果索引被定义为 -

create index t_ix_field3 on t (case when field3 = 101 then field3 end); 
Run Code Online (Sandbox Code Playgroud)

然后为了使用索引,查询应该看起来像 -

select * from t where case when field3 = 101 then field3 end = 101;
Run Code Online (Sandbox Code Playgroud)