[20190918]关于函数索引问题.txt 1.环境: SCOTT@test01p> @ ver1 PORT_STRING VERSION BANNER CON_ID ------------------------------ -------------- -------------------------------------------------------------------------------- ---------- IBMPC/WIN_NT64-9.1.0 12.2.0.1.0 Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production 0 create table t as select 1 id1, rownum id2 ,'test' name from dual connect by level<1e4; insert into t values (1e4,1e4,'abcd'); commit ; create index if_t_id2 on t(decode(id1, 1, to_number(null), id2)); --//分析表略。 --//简单说明,使用to_number(null)保证返回数据类型是number类型的NULL值。 2.测试: SCOTT@test01p> select column_name,data_type from user_tab_cols where table_name = 'T' ; COLUMN_NAME DATA_TYPE -------------------- ---------- ID1 NUMBER ID2 NUMBER NAME CHAR SYS_NC00004$ NUMBER --//增加一个隐含字段SYS_NC00004$.返回数据类型是number类型. SCOTT@test01p> alter session set statistics_level = all; Session altered. SCOTT@test01p> select * from t where decode(id1, 1,to_number(null), id2) = 1e4; ID1 ID2 NAME ---------- ---------- -------------------- 10000 10000 abcd SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID 7srfk2yjdxx49, child number 0 ------------------------------------- select * from t where decode(id1, 1,to_number(null), id2) = 1e4 Plan hash value: 1601196873 -------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | -------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 10 (100)| | 1 |00:00:00.01 | 31 | |* 1 | TABLE ACCESS FULL| T | 1 | 100 | 1200 | 10 (0)| 00:00:01 | 1 |00:00:00.01 | 31 | -------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(DECODE("ID1",1,NULL,"ID2")=10000) --//你可以发现实际上filter(DECODE("ID1",1,NULL,"ID2")=10000). SCOTT@test01p> select * from user_ind_expressions where index_name = 'IF_T_ID2' 2 @prxx ============================== INDEX_NAME : IF_T_ID2 TABLE_NAME : T COLUMN_EXPRESSION : DECODE("ID1",1,NULL,"ID2") COLUMN_POSITION : 1 PL/SQL procedure successfully completed. --//你可以发现我建立的函数索引的表达式与保存的不一致. --//尝试改写看看呢? SCOTT@test01p> select * from t where decode(id1, 1,null, id2) = 1e4; ID1 ID2 NAME ---------- ---------- -------------------- 10000 10000 abcd SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID by0609fp41hy2, child number 0 ------------------------------------- select * from t where decode(id1, 1,null, id2) = 1e4 Plan hash value: 1130968923 ------------------------------------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | | 2 (100)| | 1 |00:00:00.01 | 2 | | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 1 | 1 | 13 | 2 (0)| 00:00:01 | 1 |00:00:00.01 | 2 | |* 2 | INDEX RANGE SCAN | IF_T_ID2 | 1 | 1 | | 1 (0)| 00:00:01 | 1 |00:00:00.01 | 1 | ------------------------------------------------------------------------------------------------------------------------------------------ Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 2 - SEL$1 / T@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("T"."SYS_NC00004$"=10000) --//这样可以使用索引,而这样明显存在1个错误,按照Yangtingkun以前blog介绍,这样的返回类型是字符型.因为NULL没有明确指定 --//缺省类型是varchar2类型.而实际现在是number类型.是因为SYS_NC00004$是NUMBER类型. 3.继续测试: --//如果rebuild online索引呢? SCOTT@test01p> alter index IF_T_ID2 rebuild online ; Index altered. SCOTT@test01p> select * from t where decode(id1, 1,null, id2) = 1e4; ID1 ID2 NAME ---------- ---------- -------------------- 10000 10000 abcd SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID by0609fp41hy2, child number 0 ------------------------------------- select * from t where decode(id1, 1,null, id2) = 1e4 Plan hash value: 1601196873 -------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | -------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 11 (100)| | 1 |00:00:00.01 | 31 | |* 1 | TABLE ACCESS FULL| T | 1 | 1 | 13 | 11 (10)| 00:00:01 | 1 |00:00:00.01 | 31 | -------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(TO_NUMBER(DECODE("ID1",1,NULL,TO_CHAR("ID2")))=10000) --//注意看过滤条件,发生了隐式转换.前面加上了TO_NUMBER. SCOTT@test01p> select column_name,data_type from user_tab_cols where table_name = 'T' ; COLUMN_NAME DATA_TYPE -------------------- -------------------- ID1 NUMBER ID2 NUMBER NAME CHAR SYS_NC00004$ VARCHAR2 --//重建索引后,隐含字段SYS_NC00004$的数据类型对比前面的情况发生了变化,变为varchar2类型. --//要保证使用索引应该写成如下: SCOTT@test01p> select * from t where decode(id1, 1,null, id2) = to_char(1e4); ID1 ID2 NAME ---------- ---------- -------------------- 10000 10000 abcd SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID 63zyt23ufr2xa, child number 0 ------------------------------------- select * from t where decode(id1, 1,null, id2) = to_char(1e4) Plan hash value: 1130968923 ------------------------------------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | | 2 (100)| | 1 |00:00:00.01 | 2 | | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 1 | 1 | 13 | 2 (0)| 00:00:01 | 1 |00:00:00.01 | 2 | |* 2 | INDEX RANGE SCAN | IF_T_ID2 | 1 | 1 | | 1 (0)| 00:00:01 | 1 |00:00:00.01 | 1 | ------------------------------------------------------------------------------------------------------------------------------------------ Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / T@SEL$1 2 - SEL$1 / T@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("T"."SYS_NC00004$"='10000')
[20190918]关于函数索引问题.txt
来源:这里教程网
时间:2026-03-03 14:13:43
作者:
编辑推荐:
下一篇:
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- iPhone手机全家桶出炉,一分钟带你回顾从99到1449美元的发展史
iPhone手机全家桶出炉,一分钟带你回顾从99到1449美元的发展史
26-03-03 - Oracle 20c 新特性: SQL 宏支持(SQL Macro)Scalar 和 Table 模式 两种用法
- 数据库软件被注入恶意代码,导致数据库无法启动,ORA-600_16703
数据库软件被注入恶意代码,导致数据库无法启动,ORA-600_16703
26-03-03 - 从零开始入门 K8s| 阿里技术专家详解 K8s 核心概念
从零开始入门 K8s| 阿里技术专家详解 K8s 核心概念
26-03-03 - 为什么很少有手机厂家生产纯白色手机,原来因为这3个原因
为什么很少有手机厂家生产纯白色手机,原来因为这3个原因
26-03-03 - 从快速增长到岌岌可危,雪加电子烟只用了不到半年时间?
从快速增长到岌岌可危,雪加电子烟只用了不到半年时间?
26-03-03 - 前程无忧恐难无忧
前程无忧恐难无忧
26-03-03 - 十岁微博的新焦虑
十岁微博的新焦虑
26-03-03 - 苹果手机老收到垃圾短信,教你3招,开启正确屏蔽方式
苹果手机老收到垃圾短信,教你3招,开启正确屏蔽方式
26-03-03 - 小米手机MIUI11带有3个实用小功能,与家庭相关,保护家人安全
小米手机MIUI11带有3个实用小功能,与家庭相关,保护家人安全
26-03-03
