当WHERE子句对某一列使用函数时,除非利用这个简单的技术强制索引,否则Oracle优化器不能在查询中使用索引。

通常情况下,如果在WHERE子句中不使用诸如UPPER、REPLACE 或SUBSTRD等函数,就不能对指定列建立特定的条件。但如果使用了这些函数,则会出现一个问题:这些函数会阻碍Oracle优化器对列使用索引,因而与采用索引的情况相比较,查询会花费更多的时间。

庆幸的是,如果在使用函数的这些列中包含了字符型数据,可以用这样一种方法修改查询语句,以达到强制性使用索引,更有效地运行查询。这篇文章介绍了涉及的技术,并说明了在两种典型情况下怎样实现。

大小写混合情况

在讨论由于函数修改了列的内容,如何强制使用索引前,让我们首先看看为什么Oracle优化器在这种情况下不能使用索引。假定我们要搜寻包含了大小写混合的数据,如ADDRESS表的NAME列。因为数据是用户输入的,我们无法使用已经统一改为大写的数据。为了找到每一个名为john的地址,我们使用包含了UPPER子句的查询语句。如下所示:

SQL> select address from address where upper(name) like 'JOHN';

在运行这个查询语句前,如果我们运行了命令“set autotrace on”,将会得到下列结果,其中包含了执行过程:

ADDRESS

cleveland

1 row selected.

Execution Plan

SELECT STATEMENT

TABLE ACCESS FULL ADDRESS

可以看到,在这种情况下,Oracle优化器对ADDRESS 表作了一次完整的扫描,而没有使用NAME 列的索引。这是因为索引是根据列中数据的实际值建立的,而UPPER 函数已经将字符转换成大写,即修改了这些值,因此该查询不能使用这列的索引。优化器不能与索引项比较“JOHN”,没有索引项对应于“JOHN”-只有“john”。

值得庆幸的是,如果在这种情况下想要强制使用索引,有一种简便的方法:只要在WHERE 子句中增加一个或多个特定的条件,用于测试索引值,并减少需要扫描的行,但这并没有修改原来SQL 编码中的条件。以下列查询语句为例:

SQL> select address from address where upper(name) like 'JO%' AND (name

like 'J%' or name like 'j%');

使用这种查询语句(已设置AUTOTRACE),可得到下列结果:

ADDRESS

cleveland

1 row selected.

Execution Plan

SELECT STATEMENT

CONCATENATION

TABLE ACCESS BY INDEX ROWID ADDRESS

INDEX RANGE SCAN ADDRESS_I

TABLE ACCESS BY INDEX ROWID ADDRESS

INDEX RANGE SCAN ADDRESS_I

现在,优化器为WHERE 子句中AND 联结的两个语句中每一个语句确定的范围进行扫描----第二个语句没有引用函数,因而使用了索引。在两个范围扫描后,将运行结果合并。

在这个例子中,如果数据库有成百上千行,可以用下列方法扩充WHERE 子句,进一步缩小扫描范围:

select address from address where

upper(name) like 'JOHN' AND (name like 'JO%'

or name like 'jo%' or name like 'Jo' or name like 'jO' );

得到的结果与以前相同,但是,其执行过程如下所示,表明有4个扫描范围。

Execution Plan

SELECT STATEMENT

CONCATENATION

TABLE ACCESS BY INDEX ROWID ADDRESS

INDEX RANGE SCAN ADDRESS_I

TABLE ACCESS BY INDEX ROWID ADDRESS

INDEX RANGE SCAN ADDRESS_I

TABLE ACCESS BY INDEX ROWID ADDRESS

INDEX RANGE SCAN ADDRESS_I

TABLE ACCESS BY INDEX ROWID ADDRESS

INDEX RANGE SCAN ADDRESS_I

如果试图进一步提高查询速度,我们可以在特定的“name like”条件中指明3个或更多的字符。然而,这样做会使得WHERE子句十分笨重。因为需要大小写字符所有可能的组合-joh ,Joh,jOh,joH等等。除此之外,指定一个或两个字符已足以加快查询的运行速度了。

现在让我们看看,当我们引用不同的函数时,怎样运用这个基本技术。

使用REPLACE的情况

正如名字不总是以大写输入一样,电话号码也会以许多格式出现: 如 123-456-7890, 123 456 7890,(123)456-7890 等等。

如果在列名为 PHONE_NUMBER中搜寻上述号码时,可能需要使用函数REPLACE以保证统一的格式。如果在PHONE_NUMBER列中只包含空格、连字符和数字,where 子句可以如下所示:

WHERE replace(replace(phone_number , '-' ) , ' ' ) = '1234567890'

WHERE子句两次使用REPLACE 函数去掉了连字符和空格,保证了电话号码是简单的数字串。然而,该函数阻止了优化器在该列使用索引。因此,我们按如下方法修改WHERE子句,以强制执行索引。

WHERE replace(replace(phone_number, '-' ) , ' ' ) = '1234567890'

AND phone_number like '123% '如果我们知道数据中可能包含圆括号,WHERE 子句会稍微复杂一点。我们可以再增加REPLACE 函数(去掉圆括号、连字符和空格),按如下所示扩充增加的条件:

WHERE replace(replace(replace(replace

(phone_number , ' - ' ) ,' '),'( ' )

, ' ) ' ) = '1234567890' AND

(phone number like ' 123% '

or phone_number like ' (123% ' ) '

该例强调了巧妙地选用WHERE 子句条件的重要性,而且,这些条件不会改变查询结果。你的选择应基于完全了解该列中存在的信息类型。在该例中,我们需要知道 PHONE_NUMBER 数据中存在几种不同的格式,这样,我们能够修改WHERE 子句而不会影响查询结果。

正确的条件

以后当你遇到包含CHARACTER 数据修改函数列的WHERE 子句时,应考虑怎样利用增加一个或两个特定的条件,迫使优化器使用索引。适当地选择一组特定的条件能减少扫描行,并且强制使用索引不会影响查询结果----但却提高了查询的执行速度。

【责任编辑:火凤凰 TEL:(010)68476606-8007】

oracle加强制索引,Oracle中建立索引并强制优化器使用相关推荐

  1. oracle 视图能建索引吗,Oracle视图中建立索引注意事项.doc

    Oracle视图中建立索引的注意事项 在视图上创建索引需要三个条件:一.视图必须绑定到架构.要做到这点,在?CREATE?VIEW?语句中,必须加上?WITH?SCHEMABINDING,如果是使用企 ...

  2. solr从pdf、office文档中建立索引

    2015年05月28日 ⁄ hadoop ⁄ 评论数 1 使用solr从pdf.office文档中建立索引和从数据库中建立相似,只不过这里需要tika来解析这些文档.8.1 配置一个handler 这 ...

  3. [转载] 使用Python在Pandas Dataframe中建立索引

    参考链接: 用Pandas建立索引并选择数据 In Numpy arrays, we are familiar with the concepts of indexing, slicing, and ...

  4. 计算机二级vf索引建立,计算机二级VFP辅导:在VFP中建立索引文件的方法

    考试大编辑整理: 在VFP中建立索引文件的方法 1.用命令建立索引 命令格式是: INDEX ON(索引表达式) TO] [FOR(条件)][c()MPACT][ASCENI)ING l I)ESCE ...

  5. 什么是索引?为什么要建立索引?并举例说明.(以某一具体的DBMS为例)

    什么是索引?为什么要建立索引?并举例说明.(以某一具体的DBMS为例) 悬赏分:100 - 解决时间:2008-7-7 16:40 什么是聚簇索引?为什么要建立聚簇索引?并举例说明. 希望可以一起回答 ...

  6. 搜索引擎索引之如何建立索引

                                              本文节选自<这就是搜索引擎:核心技术详解>第三章 3.4建立索引 正如前述章节所述,索引结构如果建立好了 ...

  7. MySQL普通索引与唯一索引__mysql中唯一索引和普通索引的用途及区别

    MySQL普通索引与唯一索引 索引作用: 提高查询效率,一般加在经常查询或者排序的字段上. 普通索引: 允许字段值重复 唯一索引: 保证数据记录唯一性 如何选择: 查询过程: 对普通索引来说,找到满足 ...

  8. 6.ES中什么是索引(ES中的索引指的是库)的分片和备份(副本)?ES中的关键词有哪些? 嘻哈的简写笔记——Elastic Search

    1.ES中什么是索引(ES中的索引指的是库)的分片和备份(副本)? 分片是对索引的切分存储:备份是对分片的备份: ES的服务中,可以创建多个索引(ES中的索引指的是库):每一个索引默认被分成5片存储: ...

  9. 【Oracle】看懂执行计划之基于成本的优化器(CBO)

    [Oracle]看懂执行计划之基于成本的优化器(CBO) 基于代价的优化方式   Cost-Based Optimization,简称 CBO.CBO 选择目标 SQL 执行计划的判断原则是成本,从目 ...

  10. 浅谈Android中的异步加载之ListView中图片的缓存及优化三

    隔了很久没写博客,现在必须快速脉动回来.今天我还是接着上一个多线程中的异步加载系列中的最后一个使用异步加载实现ListView中的图片缓存及其优化.具体来说这次是一个综合Demo.但是个人觉得里面还算 ...

最新文章

  1. visual studio asmx 调试_通过Windows Visual Studio远程调试WSL2中的.NET Core Linux应用程序...
  2. 介绍一下Linux 误删文件恢复命令及方法
  3. 作业4(列表增加或者修改)
  4. 计算机二级题31套资料,计算机等级考试:二级VFP机试第31套
  5. Ember 3.9 发布,3.8 升级为 LTS
  6. eclipse没有日志_技术进展 | 加强公共DHT抵抗eclipse攻击!
  7. Hive的连接(join)方案
  8. 加菲猫软件显示不能链接服务器,sql server 2012 链接服务器不能链接sql server 2000的解决方案...
  9. wcf、web api、webservicer 之间的区别
  10. 一起玩转CAN卡“第五通道”吧!
  11. LaTeX 常用符号大全(from wikipedia)
  12. Python实战 | 手拉手教你爬取贝壳房源数据
  13. 数据结构第七次作业·第四题·北京地铁线路查询Dijkstra算法
  14. Banner打造广告自动轮播图
  15. QQ “安全检查未通过,禁止下载该文件” 解决方法
  16. matplotlib画图并设置图片大小
  17. 一款仿古文本编辑器---edit.exe
  18. python统计汉字个数是_Python入门(一):一句话统计文章不重复汉字数
  19. Springboot毕业设计管理系统
  20. 蓝桥杯 并查集汇总学习 及其代码

热门文章

  1. 全球与中国硅外延片市场深度研究分析报告
  2. java枚举类循环_(转载)java 枚举 循环遍历以及一些简单常见的使用
  3. 扫码器.java_条码扫描器在Java上的实现
  4. 游侠原创:vmware下android-x86-4.4-RC1体验
  5. 手机flash插件Android2.3.4,android2.3.4手机安装adobe flash player 后不知怎么使用?
  6. matlab 使用 audiorecorder、recordblocking录制声音,play 播放声音,audiowrite 保存声音
  7. 黑苹果引导工具:Clover for Mac
  8. 遇到电脑打字没有候选字框解决办法
  9. 用Python解析吃鸡游戏的真相
  10. Linux介绍和命令