在Oracle中,函数索引是什么?
♣ 答案部分
在Oracle中,有一类特殊的索引,称为函数索引(Function-Based Indexes,FBI),它基于对表中列进行计算后的结果创建索引。函数索引在不修改应用程序的逻辑基础上提高了查询性能。如果没有函数索引,那么任何在列上执行了函数的查询都不能使用这个列的索引。当在查询中包含该函数时,数据库才会使用该函数索引。函数索引可以是一个B-Tree索引或位图索引。
用于生成索引的函数可以是算术表达式,也可以是一个包含SQL函数、用户定义PL/SQL函数、包函数,或C调用的表达式。当数据库处理INSERT和UPDATE语句时,它仍然必须计算函数才能完成对语句的处理。
对于函数索引的索引列的函数查询可以通过视图DBA_IND_EXPRESSIONS来实现,通过如下的SQL语句可以查询所有的函数索引:
SELECT * FROM DBA_INDEXES D WHERE D.INDEX_TYPE LIKE 'FUNCTION-BASED%';
函数索引必须遵守下面的规则:
① 必须使用基于成本的优化器,而且创建后必须对索引进行分析。
② 如果被函数索引所引用的用户自定义PL/SQL函数失效了或该函数索引的属主没有了在函数索引里面使用的函数的执行权限,那么对这张表上的执行的所有的操作(例如SELECT查询、DML等)也将失败(会报错:ORA-06575: Package or function F_R1_LHR is in an invalid state或ORA-00904: : invalid identifier)。这时,可以重新修改自定义函数并在编译无报错通过后,该表上所有的DML和查询操作将恢复正常。
③ 创建函数索引的函数必须是确定性的。即,对于指定的输入,总是会返回确定的结果。
④ 在创建索引的函数里面不能使用SUM、COUNT等聚合函数。
⑤ 不能在LOB类型的列、NESTED TABLE列上创建函数索引。
⑥ 不能使用SYSDATE、USER等非确定性函数。
⑦ 对于任何用户自定义函数必须显式的声明DETERMINISTIC关键字,否则会报错:“ora-30553: the function is not deterministic”。
需要注意的是,使用函数索引有几个先决条件:
(1)必须拥有CREATE INDEX和QUERY REWRITE(本模式下)或CREATE ANY INDEX和GLOBAL QUERY REWRITE(其它模式下)权限。其赋权语句分别为“GRANT QUERY REWRITE TO LHR;”和“GRANT GLOBAL QUERY REWRITE TO LHR;”。
(2)必须使用基于成本的优化器,基于规则的优化器将被忽略。
(3)参数QUERY_REWRITE_INTEGRITY和QUERY_REWRITE_ENABLED可以保持默认值。
QUERY_REWRITE_INTEGRITY = ENFORCED
QUERY_REWRITE_ENABLED = TRUE(从Oracle 10g开始默认为TRUE)
这里举一个基于函数的索引的例子。
首先为函数索引的建立及数据做准备:
1SYS@lhrdb> CREATE TABLE TESTFINDEX_LHR(ID NUMBER,SCHR VARCHAR2(10));
2Table created.
3SYS@lhrdb> CREATE INDEX IND_FUN ON TESTFINDEX_LHR(UPPER(SCHR));
4Index created.
5SYS@lhrdb> INSERT INTO TESTFINDEX_LHR VALUES(1,'a');
61 row created.
7SYS@lhrdb> COMMIT;
8Commit complete.
9
10--因为强制使用基于规则的优化器,所以,不会使用函数索引:
11SYS@lhrdb> SELECT /*+ RULE*/ * FROM TESTFINDEX_LHR WHERE UPPER(SCHR)='A';
12 ID SCHR
13---------- ----------
14 1 a
15Execution Plan
16----------------------------------------------------------
17Plan hash value: 940247041
18--------------------------------------------
19| Id | Operation | Name |
20--------------------------------------------
21| 0 | SELECT STATEMENT | |
22|* 1 | TABLE ACCESS FULL| TESTFINDEX_LHR |
23--------------------------------------------
24Predicate Information (identified by operation id):
25---------------------------------------------------
26 1 - filter(UPPER("SCHR")='A')
27Note
28-----
29 - rule based optimizer used (con����,ݰ��sider using cbo)
30
31
32--这里优化器选择了全表扫描,若在不使用基于规则的优化器的情况下,则该查询会选择函数索引IND_FUN:
33SYS@lhrdb> SELECT * FROM TESTFINDEX_LHR WHERE UPPER(SCHR)='A';
34 ID SCHR
35---------- ----------
36 1 a
37Execution Plan
38----------------------------------------------------------
39Plan hash value: 967513602
40----------------------------------------------------------------------------------------------
41| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
42----------------------------------------------------------------------------------------------
43| 0 | SELECT STATEMENT | | 1 | 27 | 1 (0)| 00:00:01 |
44| 1 | TABLE ACCESS BY INDEX ROWID| TESTFINDEX_LHR | 1 | 27 | 1 (0)| 00:00:01 |
45|* 2 | INDEX RANGE SCAN | IND_FUN | 1 | | 1 (0)| 00:00:01 |
46----------------------------------------------------------------------------------------------
47Predicate Information (identified by operation id):
48---------------------------------------------------
49 2 - access(UPPER("SCHR")='A')
50Note
51-----
52 - dynamic sampling used for this statement (level=2)
53SYS@lhrdb> SELECT D.TABLE_NAME,D.COLUMN_EXPRESSION FROM DBA_IND_EXPRESSIONS D WHERE D.INDEX_NAME='IND_FUN';
54
55TABLE_NAME COLUMN_EXPRESSION
56------------------------------ ----------------------
57TESTFINDEX_LHR UPPER("SCHR")
可见,例子中使用了IND_FUN函数索引,且函数可以通过视图DBA_IND_EXPRESSIONS来查询。
本文选自《Oracle程序员面试笔试宝典》,作者:李华荣。
详细内容可以添加麦老师微信或QQ私聊。
● 本文作者:小麦苗,只专注于数据库的技术,更注重技术的运用
● 作者博客地址:http://blog.itpub.net/26736162/abstract/1/
● 本系列题目来源于作者的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解
● 版权所有,欢迎分享本文,转载请保留出处
● QQ:646634621 QQ群:618766405
● 提供OCP、OCM和高可用部分最实用的技能培训
● 题目解答若有不当之处,还望各位朋友批评指正,共同进步
DBA宝典
长按下图识别二维码或微信扫描下图二维码来关注小麦苗的微信公众号:xiaomaimiaolhr,学习最实用的数据库技术。
本文分享自微信公众号 - DB宝(lhrdba)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。