[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. Android Studio如何配置CURL指令一键打包apk上传至蒲公英

    Android Studio如何配置CURL指令一键打包apk上传至蒲公英 第一步:在所需要打包的模块build.gradle文件中加入如下代码: android{ buildTypes { //配置 ...

  2. & 和 && 的区别,与(&)运算符、位移运算符(<< 、>>、>>>)的含义及使用(Java示例)

    & 和 && 的区别,与(&)运算符.位移运算符(<< .>>.>>>)的含义及使用(Java示例) 1. & 和 & ...

  3. ArrayList的输出以及一些问题

    //首先需要创建一个ArrayList ArrayList arr=new ArrayList(); //然后往ArrayList里面插入一些值 arr.add("a"); arr ...

  4. 【Oracle】常用函数

    来源自:https://www.cnblogs.com/lxl57610/p/7442130.html Oracle SQL 提供了用于执行特定操作的专用函数.这些函数大大增强了 SQL 语言的功能. ...

  5. HttpClient之用CloseableHttpClient发送post请求

    使用HttpClient发送请求的一般步骤(1) 创建HttpClient对象.(2)创建请求方法的实例,并指定请求URL.如果需要发送GET请求,创建HttpGet对象:如果需要发送POST请求,创 ...

  6. Codeforces Round #594 (Div. 1) A. Ivan the Fool and the Probability Theory 动态规划

    A. Ivan the Fool and the Probability Theory Recently Ivan the Fool decided to become smarter and stu ...

  7. 第04组 Alpha冲刺(2/4)

    队名:斗地组 组长博客:地址 作业博客:Alpha冲刺(2/4) 各组员情况 林涛(组长) 过去两天完成了哪些任务: 1.收集各个组员的进度 2.写博客 展示GitHub当日代码/文档签入记录: 接下 ...

  8. Linux 命名管道

    前文中笔者介绍了管道,本文接着介绍命名管道.文中演示所用环境为 Ubuntu 18.04 desktop. 命名管道(named pipe)又被称为先进先出队列(FIFO),是一种特殊的管道,存在于文 ...

  9. 深入理解typescript的Functions

    Functions Introduction # Functions are the fundamental building block of any application in JavaScri ...

  10. Eclipse引入自定义XML约束文件(DTD,SCHEMA)问题

    Eclipse引入自定义XML约束文件(DTD,SCHEMA)问题 1:说明 使用Eclipse 编写xml文件的约束文件的,包括DTD约束文件,Schema约束文件的时候, 我们也需要接受eclip ...