您的位置:首页 > 数据库 > Oracle

Oracle的选择函数索引实验

2006-04-02 02:23 417 查看
选择函数索引在某些场合的使用,可以大大减少索引存储空间,并且一定程度提高查询速度.
特别适合于这种情况:
列的值呈现明显的典型特征,并且查询时,主要针对某一个典型值返回结果.
例如:病人挂号记录的执行状态为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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: