[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的更多相关文章

  1. [20180408]那些函数索引适合字段的查询.txt

    [20180408]那些函数索引适合字段的查询.txt --//一般不主张建立函数索引,往往是开发的无知,使用trunc等函数,实际上一些函数也可以用于字段的查询.--//以前零碎的写过一些,放假看了 ...

  2. Oracle索引梳理系列(六)- Oracle索引种类之函数索引

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  3. MySQL 5.7新特性之Generated Column(函数索引)

    MySQL 5.7引入了Generated Column,这篇文章简单地介绍了Generated Column的使用方法和注意事项,为读者了解MySQL 5.7提供一个快速的.完整的教程.这篇文章围绕 ...

  4. 【Oracle 函数索引】一次数据库的优化过程

    [问题]表里数据2万条,查询执行时间 818087.38 ms(12分钟). SQL语句如下:select   F1,F2,F3,F4   from t_sms_g_send t   left joi ...

  5. 利用函数索引优化<>

    SQL> select count(*),ID from test_2 group by id; COUNT(*) ID ---------- ---------- 131072 1 11796 ...

  6. oracle的位图索引和函数索引

    1.位图索引 位图索引适用于性别.婚姻状态.行政区等只有几列固定值的类型列,身份证号等就不适合位图索引,位图索引适用于静态数据,频繁更新的字段不适用建立位图索引,因为更新会导致索引块区的变更,还会引起 ...

  7. SQLServer中间接实现函数索引或者Hash索引

    本文出处:http://www.cnblogs.com/wy123/p/6617700.html SQLServer中没有函数索引,在某些场景下查询的时候要根据字段的某一部分做查询或者经过某种计算之后 ...

  8. Oracle中的位图索引和函数索引

    位图索引 同样的,先说是什么,再说为什么. 上篇我们说过BTREE索引是将数据表的索引列和行号排序后以树状形式存在磁盘中.那位图索引是什么样的呢? 现有如下日志表,有操作类型字段op_type,该字段 ...

  9. MySQL5.7 虚拟列实现表达式或函数索引

    MySQL5.7 虚拟列实现表达式或函数索引 http://www.linuxidc.com/Linux/2015-11/125162.htm https://dev.mysql.com/doc/re ...

随机推荐

  1. CSS学习笔记-边框图片等属性

      1.边框图片:        1.1含义:            告诉浏览器指定一张图片作为边框        1.2格式:             border-image-source:url ...

  2. Beyond Compare 4.X 破解方法(亲测有效)

    Windows下Beyond Compare 4 30天评估到期了的话,可以尝试下面两种方式: 破解方式把Beyond Compare 4安装文件夹下面的BCUnrar.dll文件删掉就行了,但是这种 ...

  3. Object-C里的类目,延展,协议

    1.类目 类目就是为已存在的类添加新的方法.但是不能添加实例变量.比如系统的类,我们看不到他的.m文件,所以没有办法用直接添加方法的方式去实现. @interface NSMutableArray ( ...

  4. linux学习(八)Shell中变量的数学运算

    目录 常见的运算符 expr命令 @(Shell中变量的数学运算) 常见的运算符 环境变量 说明 + 加 - 减 * 乘 / 除 % 取模 因为Shell中将*作为通配符使用, expr命令 expr ...

  5. PHP 部分语法(一)

    PHP: PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言,它以 <?php 开始,并以 ?> 结束: 它还是一门弱类型语言,类型不需显式声明 变量: PHP 没有声明变量的命令 ...

  6. 小程序组件化开发框架---wepy 项目创建

    wepy是一个优秀的微信小程序组件化框架,突破了小程序的限制,支持了npm包加载以及组件化方案.这里就以我个人的经历讲下怎么创建wepy项目. 1.首先 在桌面(自己选定目录下)新建一个文件夹,注意需 ...

  7. [Go] Golang中的面向对象

    struct interface 就可以实现面向对象中的继承,封装,多态 继承的演示:Tsh类型继承People类型,并且使用People类型的方法 多态的演示Tsh类型实现了接口Student,实现 ...

  8. Java学习笔记(5)--- Number类和Math 类,String类的应用,Java数组入门

    1.Number 和 Math 类: 在实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型(int,double,float这些)的情形. 这种由编译器特别支持的包装称为装箱,所以当内置数 ...

  9. Day5- Python基础5 模块导入、time、datetime、random、os、sys、hashlib、json&pickle

    本节目录: 1.模块的分类 2.模块的导入 3.time模块 4.datetime模块 5.random 6.os模块 7.sys模块 8.hashlib 9.json&pickle 一.模块 ...

  10. 面向对象程序设计(JAVA) 第12周学习指导及要求

    2019面向对象程序设计(Java)第12周学习指导及要求 (2019.11.15-2019.11.18)   学习目标 (1) 掌握Vetor.Stack.Hashtable三个类的用途及常用API ...