SQL优化中索引列使用函数之灵异事件

SQL优化内容中有一种说法说的是避免在索引列上使用函数、运算等操作,否则Oracle优化器将不使用索引而使用全表扫描,但是也有一些例外的情况,今天我们就来看看该灵异事件。

  一般而言,以下情况都会使Oracle的优化器走全表扫描,举例:

  1.         substr(hbs_bh,1,4)=’5400’,优化处理:hbs_bh like ‘5400%’

  2.         trunc(sk_rq)=trunc(sysdate), 优化处理:sk_rq>=trunc(sysdate) and sk_rq<trunc(sysdate+1)

  3.         进行了显式或隐式的运算的字段不能进行索引,如:

  ss_df+20>50,优化处理:ss_df>30

  'X' || hbs_bh>’X5400021452’,优化处理:hbs_bh>'5400021542'

  sk_rq+5=sysdate,优化处理:sk_rq=sysdate-5

  4.         条件内包括了多个本表的字段运算时不能进行索引,如:ys_df>cx_df,无法进行优化

  qc_bh || kh_bh='5400250000',优化处理:qc_bh='5400' and kh_bh='250000'

  5.  避免出现隐式类型转化

  hbs_bh=5401002554,优化处理:hbs_bh='5401002554',注:此条件对hbs_bh 进行隐式的to_number转换,因为hbs_bh字段是字符型。

  有一些其它的例外情况,如果select 后边只有索引列且where查询中的索引列含有非空约束的时候,以上规则不适用,如下示例:

  先给出所有脚本及结论:

  drop table t  purge;

  Create Table t  nologging As select *  from    dba_objects d ;

  create   index ind_objectname on  t(object_name);

  select t.object_name from t where t.object_name ='T';        --走索引

  select t.object_name from t where UPPER(t.object_name) ='T';       --不走索引

  select t.object_name from t where UPPER(t.object_name) ='T' and t.object_name IS NOT NULL ;           --走索引  (INDEX FAST FULL SCAN)

  select t.object_name from t where UPPER(t.object_name) ||'AAA' ='T'||'AAA' and t.object_name IS NOT NULL ;     --走索引  (INDEX FAST FULL SCAN)

  select t.object_name,t.owner from t where UPPER(t.object_name) ||'AAA' ='T'||'AAA' and t.object_name IS NOT NULL ;     --不走索引

  测试代码:


C:\Users\华荣>sqlplus lhr/lhr@orclasm

SQL*Plus: Release 11.2.0.1.0 Production on 星期三 11月 12 10:52:29 2014

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

连接到:

Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

With the Partitioning, Automatic Storage Management, OLAP, Data Mining

and Real Application Testing options

SQL>

SQL>

SQL> drop table t  purge;

表已删除。

SQL> Create Table t  nologging As select *  from    dba_objects d ;

表已创建。

SQL>  create   index ind_objectname on  t(object_name);

索引已创建。

 ---- t表所有列均可以为空


SQL> desc t

Name                      Null?    Type

----------------------------------------- -------- ----------------------------

OWNER                               VARCHAR2(30)

OBJECT_NAME                         VARCHAR2(128)

SUBOBJECT_NAME                      VARCHAR2(30)

OBJECT_ID                           NUMBER

DATA_OBJECT_ID                      NUMBER

OBJECT_TYPE                         VARCHAR2(19)

CREATED                             DATE

LAST_DDL_TIME                       DATE

TIMESTAMP                           VARCHAR2(19)

STATUS                              VARCHAR2(7)

TEMPORARY                           VARCHAR2(1)

GENERATED                           VARCHAR2(1)

SECONDARY                           VARCHAR2(1)

NAMESPACE                           NUMBER

EDITION_NAME                        VARCHAR2(30)

SQL>

SQL>  set autotrace traceonly;

SQL>  select t.object_name from t where t.object_name ='T';

执行计划

----------------------------------------------------------

Plan hash value: 4280870634

-----------------------------------------------------------------------------------

| Id  | Operation        | Name           | Rows  | Bytes | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------------

|   0 | SELECT STATEMENT |                |     1 |    66 |     3   (0)| 00:00:01 |

|*  1 |  INDEX RANGE SCAN| IND_OBJECTNAME |     1 |    66 |     3   (0)| 00:00:01 |

-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - access("T"."OBJECT_NAME"='T')

Note

-----

- dynamic sampling used for this statement (level=2)

- SQL plan baseline "SQL_PLAN_503ygb00mbj6k165e82cd" used for this statement

统计信息

----------------------------------------------------------

34  recursive calls

43  db block gets

127  consistent gets

398  physical reads

15476  redo size

349  bytes sent via SQL*Net to client

359  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

1  rows processed

SQL>  select t.object_name from t where UPPER(t.object_name) ='T';

执行计划

----------------------------------------------------------

Plan hash value: 1601196873

--------------------------------------------------------------------------

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |    12 |   792 |   305   (1)| 00:00:04 |

|*  1 |  TABLE ACCESS FULL| T    |    12 |   792 |   305   (1)| 00:00:04 |

--------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter(UPPER("T"."OBJECT_NAME")='T')

Note

-----

- dynamic sampling used for this statement (level=2)

- SQL plan baseline "SQL_PLAN_9p76pys5gdb2b94ecae5c" used for this statement

统计信息

----------------------------------------------------------

29  recursive calls

43  db block gets

1209  consistent gets

1092  physical reads

15484  redo size

349  bytes sent via SQL*Net to client

359  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

1  rows processed

SQL>  select t.object_name from t where UPPER(t.object_name) ='T' and t.object_name IS NOT NULL ;

执行计划

----------------------------------------------------------

Plan hash value: 3379870158

---------------------------------------------------------------------------------------

| Id  | Operation            | Name           | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT     |                |    51 |  3366 |   110   (1)| 00:00:02 |

|*  1 |  INDEX FAST FULL SCAN| IND_OBJECTNAME |    51 |  3366 |   110   (1)| 00:00:02 |

---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter("T"."OBJECT_NAME" IS NOT NULL AND UPPER("T"."OBJECT_NAME")='T')

Note

-----

- dynamic sampling used for this statement (level=2)

- SQL plan baseline "SQL_PLAN_czkarb71kthws18b0c28f" used for this statement

统计信息

----------------------------------------------------------

29  recursive calls

43  db block gets

505  consistent gets

384  physical reads

15612  redo size

349  bytes sent via SQL*Net to client

359  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

1  rows processed

SQL>  select t.object_name,t.owner from t where UPPER(t.object_name) ||'AAA' ='T'||'AAA' and t.object_name IS NOT NULL ;

执行计划

----------------------------------------------------------

Plan hash value: 1601196873

--------------------------------------------------------------------------

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |    51 |  4233 |   304   (1)| 00:00:04 |

|*  1 |  TABLE ACCESS FULL| T    |    51 |  4233 |   304   (1)| 00:00:04 |

--------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter("T"."OBJECT_NAME" IS NOT NULL AND

UPPER("T"."OBJECT_NAME")||'AAA'='TAAA')

Note

-----

- dynamic sampling used for this statement (level=2)

- SQL plan baseline "SQL_PLAN_au9a1c4hwdtb894ecae5c" used for this statement

统计信息

----------------------------------------------------------

30  recursive calls

44  db block gets

1210  consistent gets

1091  physical reads

15748  redo size

408  bytes sent via SQL*Net to client

359  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

1  rows processed

SQL> select t.object_name from t where UPPER(t.object_name) ||'AAA' ='T'||'AAA' and t.object_name IS NOT NULL ;

执行计划

----------------------------------------------------------

Plan hash value: 3379870158

---------------------------------------------------------------------------------------

| Id  | Operation            | Name           | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT     |                |    51 |  3366 |   110   (1)| 00:00:02 |

|*  1 |  INDEX FAST FULL SCAN| IND_OBJECTNAME |    51 |  3366 |   110   (1)| 00:00:02 |

---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter("T"."OBJECT_NAME" IS NOT NULL AND

UPPER("T"."OBJECT_NAME")||'AAA'='TAAA')

Note

-----

- dynamic sampling used for this statement (level=2)

- SQL plan baseline "SQL_PLAN_1gu36rnh3s2a318b0c28f" used for this statement

统计信息

----------------------------------------------------------

28  recursive calls

44  db block gets

505  consistent gets

6  physical reads

15544  redo size

349  bytes sent via SQL*Net to client

359  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

1  rows processed

SQL>

  其实很好理解的,索引可以看成是小表,一般而言索引总是比表本身要小得多,如果select 后需要检索的项目在索引中就可以检索的到那么Oracle优化器为啥还去大表中寻找数据呢?

       最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-08-31 07:48:25

SQL优化中索引列使用函数之灵异事件的相关文章

SQL SERVER 2005数据库日期时间类型之灵异事件

问题描述 我现在使用的SQLSERVER2005是快速开发版的,里面的日期时间类型,以前都是正常的都能显示2009-2-202:22:23这样的形式,但今天突然发现只能显示为2009-2-202:22不知为何?打开所有的表,全都只显示到分钟,不过在查询的时候,倒是全都能查出至微秒级的.我不明白为何会这样?假如我要显示出完整的日期时间类型,我该如何做?这个不是我插入语句的问题,直接在表中写也都会自动省略掉秒,小弟分少,还望高手相助! 解决方案 解决方案二:查看一下电脑日期格式是否显示到秒!

SQL SERVER中用户定义标量函数(scalar user defined function)的性能问题

用户定义函数(UDF)分类       SQL SERVER中的用户定义函数(User Defined Functions 简称UDF)分为标量函数(Scalar-Valued Function)和表值函数(Table-Valued Function).其中表值函数又分为Inline table-valued functions和Multistatement table-valued functions.     用户定义函数(UDF)在 SQL Server 中发挥重要的作用.用户定义函数可以

在PL/SQL 开发中调试存储过程和函数的一般性方法

存储过程|函数 在PL/SQL 开发中调试存储过程和函数的一般性方法摘要: Oracle 在PLSQL中提供的强大特性使得数据库开发人员可以在数据库端完成功能足够复杂的任务, 本文将结合Oracle提供的相关程序包(package)以及一个非常优秀的第三方开发工具来介绍在PLSQL中开发及调试存储过程的方法,当然也适用于函数. 版权声明: 本文可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息.原文出处: http://www.aiview.com/notes/ora_using_

SQL Server中索引使用及维护

server|索引 在应用系统中,尤其在联机事务处理系统中,对数据查询及处理速度已成为衡量应用系统成败的标准.而采用索引来加快数据处理速度也成为广大数据库用户所接受的优化方法. 在良好的数据库设计基础上,能有效地使用索引是SQL Server取得高性能的基础,SQL Server采用基于代价的优化模型,它对每一个提交的有关表的查询,决定是否使用索引或用哪一个索引.因为查询执行的大部分开销是磁盘I/O,使用索引 提高性能的一个主要目标是避免全表扫描,因为全表扫描需要从磁盘上读表的每一个数据页,如果

T-SQL查询进阶:理解SQL Server中索引的概念,原理以及其他

简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索引的概念,需要了解大量原理性的知识,包括B树,堆,数据库页,区,填充因子,碎片,文件组等等一系列相关知识,这些知识写一本小书也不为过.所以本文并不会深入讨论这些主题. 索引是什么 索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息. 精简来说,索引是一种结构.

SQL Server2005杂谈(4):在SQL Server2005中按列连接字符串的三种方法

本文为原创,如需转载,请注明作者和出处,谢谢! 上一篇:SQL Server2005杂谈(3):四个排名函数(row_number.rank.dense_rank和ntile)的比较 最近做一个项目,遇到一个在分组的情况下,将某一列的字段值(varchar类型)连接起来的问题,类似于sum函数对int型字段值求和. 如有一个表t_table,结构和数据如图1                                           图1     其中要按着xh字段分组,并且将每一组na

SQL Server中索引使用及维护简介

在应用系统中,尤其在联机事务处理系统中,对数据查询及处理速度已成为衡量应用系统成败的标准.而采用索引来加快数据处理速度也成为广大数据库用户所接受的优化方法. 在良好的数据库设计基础上,能有效地使用索引是SQL Server取得高性能的基础,SQL Server采用基于代价的优化模型,它对每一个提交的有关表的查询,决定是否使用索引或用哪一个索引.因为查询执行的大部分开销是磁盘I/O,使用索引提高性能的一个主要目标是避免全表扫描,因为全表扫描需要从磁盘上读表的每一个数据页,如果有索引指向数据值,则查

SQL优化中查询条件内移及减少HASH JOIN的代价

以下语句完全正确,但COST较高,原因是因为AEH.AEC.AC.ACSN几张表都有数百万条记录, 由于采用了HASH连接,尝试采用优化索引等多种方式,但是由于记录过多,表的查询条件相对较少, COST下降幅度始终很有限,COST提高到1000出头已经很尽力了. Select Count(Tmp.Id) From (Select Rownum As Id, t.Entry_Id, t.Container_Id, Con.Container_Num From AEC t Inner Join AE

SQL Server中CONVERT()日期转换函数的用法

先来看语汇法  代码如下 复制代码 CONVERT(data_type(length),data_to_be_converted,style) 例1  代码如下 复制代码 SELECT CONVERT(varchar(30),getdate(),101) now 结果为: now --------------------------------------- |03/8/2013 例2  代码如下 复制代码 1> select CONVERT(varchar(8),getdate(),112)