Oracle的选择函数索引实验

选择函数索引在某些场合的使用,可以大大减少索引存储空间,并且一定程度提高查询速度.
特别适合于这种情况:
列的值呈现明显的典型特征,并且查询时,主要针对某一个典型值返回结果.
例如:病人挂号记录的执行状态为2表示正在就诊的挂号病人.
由于就诊完成后,执行状态更新为1,所以大多数情况下,该字段的值是1-待诊或2-正在就诊
如果用选择函数(Case语句或Decode)对执行状态建立索引的话,就可以只对记录状态为2或1的建立索引,
这样索引就非常小,并且索引范围扫描时,范围大大减小,查询速度更快.

以下是一个对比试验,通过试验得出如下比较结果:
比项项目      B*树索引 选择函数索引
空间占用       1.8M          0.5M
查询速度         0.06          0.02
(查询返回1312条记录)

由于函数索引有一些要求条件(例如:要求cbo,要授权等),所以,不能轻易大范围的使用.

------------------------------------------------------------------------------------------------------------
--B*树索引

SQL> alter system set QUERY_REWRITE_ENABLED=TRUE;

System altered

SQL> grant query rewrite to zlhis;

Grant succeeded

SQL> drop index 病人挂号记录_IX_执行状态;

Index dropped

SQL> CREATE INDEX 病人挂号记录_IX_执行状态 ON 病人挂号记录(执行状态) PCTFREE 10 TABLESPACE zl9Patient;

Index created

SQL> analyze table 病人挂号记录 compute statistics
  2  for table
  3  for all indexes
  4  for all indexed columns;

SQL> exec show_space('病人挂号记录_IX_执行状态','ZLHIS','INDEX');

Free Blocks.............................0
Total Blocks............................225
Total Bytes.............................1843200
Unused Blocks...........................17
Unused Bytes............................139264
Last Used Ext FileId....................11
Last Used Ext BlockId...................4297
Last Used Block.........................3

PL/SQL procedure successfully completed

SQL> Select 门诊号,姓名 From 病人挂号记录 Where 执行状态=2;

已选择1312行。

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=19 Card=1312 Bytes=35424)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF '病人挂号记录' (Cost=19 Card=1312 Bytes=35424)
   2    1     INDEX (RANGE SCAN) OF '病人挂号记录_IX_执行状态' (NON-UNIQUE) (Cost=3 Card=1312)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        196  consistent gets
          0  physical reads
          0  redo size
      42326  bytes sent via SQL*Net to client
      10082  bytes received via SQL*Net from client
         89  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       1312  rows processed

-----------------------------------------------------------
Select 门诊号,姓名
From
 病人挂号记录 Where 执行状态=2

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.02       0.02          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch       89      0.02       0.04          0        196          0        1312
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       91      0.04       0.06          0        196          0        1312

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 141 

Rows     Row Source Operation
-------  ---------------------------------------------------
   1312  TABLE ACCESS BY INDEX ROWID 病人挂号记录
   1313   INDEX RANGE SCAN (object id 53400)


------------------------------------------------------------------------------------------------------------
--选择函数索引
------------------------------------------------------------------------------------------------------------
SQL> drop index 病人挂号记录_IX_执行状态;

Index dropped

SQL> CREATE INDEX 病人挂号记录_IX_执行状态 ON 病人挂号记录(decode(执行状态,2,2,Null)) PCTFREE 10 TABLESPACE zl9Patient;

Index created

SQL> analyze table 病人挂号记录 compute statistics
  2  for table
  3  for all indexes
  4  for all indexed columns;

SQL> exec show_space('病人挂号记录_IX_执行状态','ZLHIS','INDEX');

Free Blocks.............................0
Total Blocks............................65
Total Bytes.............................532480
Unused Blocks...........................60
Unused Bytes............................491520
Last Used Ext FileId....................11
Last Used Ext BlockId...................4092
Last Used Block.........................5

PL/SQL procedure successfully completed

SQL> Select 门诊号,姓名 From 病人挂号记录 Where decode(执行状态,2,2,Null)=2;

已选择1312行。

---------------------------------------------------
注意:查询条件,必须和索引建立时的条件完全匹配,否则用不到索引,decode(执行状态,2,2,Null)
---------------------------------------------------

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1312 Bytes=35424)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF '病人挂号记录' (Cost=2 Card=1312 Bytes=35424)
   2    1     INDEX (RANGE SCAN) OF '病人挂号记录_IX_执行状态' (NON-UNIQUE) (Cost=1 Card=1312)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        196  consistent gets
          0  physical reads
          0  redo size
      42326  bytes sent via SQL*Net to client
      10082  bytes received via SQL*Net from client
         89  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       1312  rows processed

----------------------------------------------------------
Select 门诊号,姓名
From
 病人挂号记录 Where decode(执行状态,2,2,Null)=2


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch       89      0.02       0.02          0        196          0        1312
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       91      0.02       0.02          0        196          0        1312

Misses in library cache during parse: 0
Optimizer goal: CHOOSE
Parsing user id: 141 

Rows     Row Source Operation
-------  ---------------------------------------------------
   1312  TABLE ACCESS BY INDEX ROWID 病人挂号记录
   1313   INDEX RANGE SCAN (object id 53399)

原文地址:https://www.cnblogs.com/zyk/p/364620.html