在OracleE数据库的字段上建立索引的方法

当where子句对某一列使用函数时,除非利用这个简单的技术强制索引,否则Oracle优化器不能在查询中使用索引。 通常情况下,如果在WHERE子句中不使用诸如UPPER、REPLACE 或SUBSTRD等函数,就不能对指定列建立特定的条件。但如果使用了这些函数,则会出现一个问题:这些函数会阻碍Oracle优化器对列使用索引,因而与采用索引的情况相比较,查询会花费更多的时间。 庆幸的是,如果在使用函数的这些列中包含了字符型数据,可以用这样一种方法修改查询语句,以达到强制性使用索引,更有效地运行查询。这篇文章介绍了涉及的技术,并说明了在两种典型情况下怎样实现。 大小写混合情况 在讨论由于函数修改了列的内容,如何强制使用索引前,让我们首先看看为什么Oracle优化器在这种情况下不能使用索引。假定我们要搜寻包含了大小写混合的数据,如在表1中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 子句时,应考虑怎样利用增加一个或两个特定的条件,迫使优化器使用索引。适当地选择一组特定的条件能减少扫描行,并且强制使用索引不会影响查询结果----但却提高了查询的执行速度。

(0)

相关推荐

  • 在OracleE数据库的字段上建立索引的方法

    当where子句对某一列使用函数时,除非利用这个简单的技术强制索引,否则Oracle优化器不能在查询中使用索引. 通常情况下,如果在WHERE子句中不使用诸如UPPER.REPLACE 或SUBSTRD等函数,就不能对指定列建立特定的条件.但如果使用了这些函数,则会出现一个问题:这些函数会阻碍Oracle优化器对列使用索引,因而与采用索引的情况相比较,查询会花费更多的时间. 庆幸的是,如果在使用函数的这些列中包含了字符型数据,可以用这样一种方法修改查询语句,以达到强制性使用索引,更有效地运行查询

  • 浅谈Mysql哪些字段适合建立索引

    1 数据库建立索引常用的规则如下: 1.表的主键.外键必须有索引: 2.数据量超过300的表应该有索引: 3.经常与其他表进行连接的表,在连接字段上应该建立索引: 4.经常出现在Where子句中的字段,特别是大表的字段,应该建立索引: 5.索引应该建在选择性高的字段上: 6.索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引: 7.复合索引的建立需要进行仔细分析:尽量考虑用单字段索引代替: A.正确选择复合索引中的主列字段,一般是选择性较好的字段: B .复合索引的几个字段是否经常同

  • Asp.Net网站优化系列之数据库的优化措施与索引优化方法

    另外在sql server内存够用的情况下索引会被放到内存中,在内存中查找自然又会提高效率:所以我们必须得合理利用索引. 1)对什么列建索引 数据库默认情况下会对主键建聚集索引,除了这个索引之外还需要在哪些列上建索引呢?这个问题只能具体情况具体分析,要看需要优化的sql语句(通常是查询次数多,查询相应想要高的语句),根据什么列的条件进行查询. 例如:在论坛的数据库中有一张表是帖子回复表,在论坛的应用中用到最多的就是对指定帖子的某一页的回复进行查询,查询回复表的条件是主贴的id:这时候在主贴字段上

  • 用SQL建立索引的方法步骤

    进入查询窗口后,输入下面的语句: CREATE INDEX mycolumn_index ON mytable (myclumn) 这个语句建立了一个名为mycolumn_index的索引.你可以给一个索引起任何名字,但你应该在索引名中包含所索引的字段名,这对你将来弄清楚建立该索引的意图是有帮助的. 注意: 在本书中你执行任何SQL语句,都会收到如下的信息: This command did not return data,and it did not return any rows 这说明该语

  • MySQL批量插入遇上唯一索引避免方法

    一.背景 以前使用SQL Server进行表分区的时候就碰到很多关于唯一索引的问题:Step8:SQL Server 当表分区遇上唯一约束,没想到在MySQL的分区中一样会遇到这样的问题:MySQL表分区实战. 今天我们来了解MySQL唯一索引的一些知识:包括如何创建,如何批量插入,还有一些技巧上SQL: 这些问题的根源在什么地方?有什么共同点?MySQL中也有分区对齐的概念?唯一索引是在很多系统中都会出现的要求,有什么办法可以避免?它对性能的影响有多大? 二.过程 (一) 导入差异数据,忽略重

  • Oracle数据库中建立索引的基本方法讲解

    怎样建立最佳索引? 1.明确地创建索引 create index index_name on table_name(field_name) tablespace tablespace_name pctfree 5 initrans 2 maxtrans 255 storage ( minextents 1 maxextents 16382 pctincrease 0 ); 2.创建基于函数的索引 常用与UPPER.LOWER.TO_CHAR(date)等函数分类上,例: create index

  • 数据库为何要建立索引的原因说明

    这里想把之前的索引学习笔记总结一下: 首先明白为什么索引会增加速度,DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合.如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行数,大大减少遍历匹配的行数,所以能明显增加查询的速度.那么在任何时候都应该加索引么?这里有几个反例:1.如果每次都需要取到所有表记录,无论如何都必须进行全表扫描了,那么是否加索引也没有意义了.2.对非唯一的字段,例如"性别"这种大量重复值的字段,

  • mysql中datetime字段建立索引并比较大小详解

    目录 1.问题背景 2.优化过程 补充:Mysql 时间Datetime 索引不生效问题 总结 1.问题背景 最近测试库查询一个表的数据,需要用到唯一的一个日期类型字段作为 where 的子查询(查询当天的数据),就正常写了个这样的 SQL,具体的表名我就不写了: # create_time 是 datetime 类型 select * from ${tablename} where date(create_time)='20220919' limit 20; 其中字段的值样本如下: 我知道我写

  • Mysql数据库表中为什么有索引却没有提高查询速度

    背景 时间过得太快了,春节假期感觉光速般就结束了,转眼间就要继续搬砖上班了.紧接着很快就要进入金三银四的求职面试高峰期,程序猿小枫还没有找到令自己感到满意的工作.就算是在过年放假期间也在拼命的准备技术面试,这不他又梳理了下之前面试过程中面试官经常问到的关于数据库方面的一道面试题,我们来一起帮小枫看看有没有遗漏的地方吧. 面试题目--问题 面试官:看你的简历中有提到过曾经进行过索引优化的工作,那我就问问你,假设数据库表中有索引,但是进行SQL数据查询还是很慢,这种情况下应该怎么分析查询慢的原因?

  • Oracle建立二进制文件索引的方法

    正在看的ORACLE教程是:Oracle建立二进制文件索引的方法.Oracle text是Oracle的全文检索技术,是9i版本标准版和企业版的一部分.Oracle text使用标准的sql语言索引.查找.分析存储在oracle数据库.文件或者网络里的文本及文档. Oracle text能进行关于文档的语言分析,使用多种方法查找文档,包括关键字.上下文查询.逻辑操作.模式匹配.混合主题查询.HTML/XML段落查找等方法.Oracle text在包含文本和结构化的关系属性的混合查询方面具有优越性

随机推荐