(一) 建立索引常用的规则如下:
1) 表的主键、外键必须有索引;
2) 数据量超过300的表应该有索引;
3) 经常与其他表进行连接的表,在连接字段上应该建立索引;
4) 经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;
5) 索引应该建在选择性高的字段上;
6) 索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;
7) 复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:
a) 正确选择复合索引中的主列字段,一般是选择性较好的字段;
b) 复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引;
c) 如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引;
d) 如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段;
e) 如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引;
8) 频繁进行数据操作的表,不要建立太多的索引;
9) 删除无用的索引,避免对执行计划造成负面影响;
以上是一些普遍的建立索引时的判断依据。一言以蔽之,索引的建立必须慎重,对每个索引的必要性都应该经过仔细分析,要有建立的依据。因为太多的索引与不充分、不正确的索引对性能都毫无益处:在表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。 另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大。
(二) 避免对列的操作:
1) 任何对列的操作都可能导致全表扫描,这里所谓的操作包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等式的右边,甚至去掉函数。
例1:下列SQL条件语句中的列都建有恰当的索引,但30万行数据情况下执行速度却非常慢:
select * from record where substrb(CardNo,1,4)='5378'(13秒)
select * from record where amount/30< 1000(11秒)
select * from record where to_char(ActionTime,'yyyymmdd')='19991201'(10秒)
由于where子句中对列的任何操作结果都是在SQL运行时逐行计算得到的,因此它不得不进行表扫描,而没有使用该列上面的索引;如果这些结果在查询编译时就能得到,那么就可以被SQL优化器优化,使用索引,避免表扫描,因此将SQL重写如下:
select * from record where CardNo like '5378%'(< 1秒)
select * from record where amount < 1000*30(< 1秒)
select * from record where ActionTime= to_date ('19991201' ,'yyyymmdd')(< 1秒)
(三) 避免不必要的类型转换:
1) 尽量避免潜在的数据类型转换。如将字符型数据与数值型数据比较,ORACLE会自动将字符型用to_number()函数进行转换,从而导致全表扫描。
例2:表tab1中的列col1是字符型(char),则以下语句存在类型转换:
select col1,col2 from tab1 where col1>10;
应该写为: select col1,col2 from tab1 where col1>'10'
(四) 增加查询的范围限制
1) 增加查询的范围限制,避免全范围的搜索
例3:以下查询表record 中时间ActionTime小于2001年3月1日的数据
select * from record where ActionTime < to_date ('20010301' ,'yyyymm')
查询计划表明,上面的查询对表进行全表扫描,如果我们知道表中的最早的数据为2001年1月1日,那么,可以增加一个最小时间,使查询在一个完整的范围之内:
select * from record where ActionTime < to_date ('20010301' ,'yyyymm') and ActionTime > to_date ('20010101' ,'yyyymm')
后一种SQL语句将利用上ActionTime字段上的索引,从而提高查询效率。把'20010301'换成一个变量,根据取值的机率,可以有一半以上的机会提高效率。同理,对于大于某个值的查询,如果知道当前可能的最大值,也可以在Where子句中加上 “AND 列名< MAX(最大值)”。
(五) 尽量去掉"IN"、"OR"
1) 含有"IN"、"OR"的Where子句常会使用工作表,使索引失效;如果不产生大量重复值,可以考虑把子句拆开;拆开的子句中应该包含索引。
例4:select count(*) from stuff where id_no in('0','1')(23秒)
可以考虑将or子句分开:
select count(*) from stuff where id_no='0'
select count(*) from stuff where id_no='1'
然后再做一个简单的加法,与原来的SQL语句相比,查询速度更快
(六) 尽量去掉 "<>"
1) 尽量去掉 "<>",避免全表扫描,如果数据是枚举值,且取值范围固定,则修改为"OR"方式
例5:UPDATE SERVICEINFO SET STATE=0 WHERE STATE<>0;
以上语句由于其中包含了"<>",执行计划中用了全表扫描(TABLE ACCESS FULL),没有用到state字段上的索引。实际应用中,由于业务逻辑的限制,字段state为枚举值,只能等于0,1或2,而且,值等于=1,2的很少,因此可以去掉"<>",利用索引来提高效率。
修改为:UPDATE SERVICEINFO SET STATE=0 WHERE STATE = 1 OR STATE = 2 。进一步的修改可以参考第4种方法
(七) 去掉Where子句中的IS NULL和IS NOT NULL
1) Where字句中的IS NULL和IS NOT NULL将不会使用索引而是进行全表搜索,因此需要通过改变查询方式,分情况讨论等方法,去掉Where子句中的IS NULL和IS NOT NULL。
(八) 索引提高数据分布不均匀时查询效率
1) 索引的选择性低,但数据的值分布差异很大时,仍然可以利用索引提高效率。
A、数据分布不均匀的特殊情况下,选择性不高的索引也要创建。
表ServiceInfo中数据量很大,假设有一百万行,其中有一个字段DisposalCourseFlag,取值范围为枚举值:[0,1,2,3,4,5,6,7]。按照前面说的索引建立的规则,“选择性不高的字段不应该建立索引,该字段只有8种取值,索引值的重复率很高,索引选择性明显很低,因此不建索引。然而,由于该字段上数据值的分布情况非常特殊,具体如下表:
取值范围 1~5 6 7
占总数据量的百分比 1% 98% 1%
而且,常用的查询中,查询DisposalCourseFlag<6 的情况既多又频繁,毫无疑问,如果能够建立索引,并且被应用,那么将大大提高这种情况的查询效率。因此,我们需要在该字段上建立索引。
(九) like子句尽量前端匹配
1) 因为like参数使用的非常频繁,因此如果能够对like子句使用索引,将很高的提高查询的效率。
例6:select * from city where name like ‘%S%’
以上查询的执行计划用了全表扫描(TABLE ACCESS FULL),如果能够修改为:
select * from city where name like ‘S%’
那么查询的执行计划将会变成(INDEX RANGE SCAN),成功的利用了name字段的索引。这意味着Oracle SQL优化器会识别出用于索引的like子句,只要该查询的匹配端是具体值。因此我们在做like查询时,应该尽量使查询的匹配端是具体值,即使用like ‘S%’。
(十) 用Case语句合并多重扫描
1) 我们常常必须基于多组数据表计算不同的聚集。例如下例通过三个独立查询:
例8:1)select count(*) from emp where sal<1000;
2)select count(*) from emp where sal between 1000 and 5000;
3)select count(*) from emp where sal>5000;
这样我们需要进行三次全表查询,但是如果我们使用case语句:
select
count (sale when sal <1000
then 1 else null end) count_poor,
count (sale when between 1000 and 5000
then 1 else null end) count_blue_collar,
count (sale when sal >5000
then 1 else null end) count_poor
from emp;
这样查询的结果一样,但是执行计划只进行了一次全表查询。
(十一) 使用基于函数的索引
1) select * from emp where substr(ename,1,2)=’SM’;
可以创建一个带有substr函数的基于函数的索引:
create index emp_ename_substr on eemp ( substr(ename,1,2) );
这样在执行上面的查询语句时,这个基于函数的索引将排上用场,执行计划将是(INDEX RANGE SCAN)。
(十二) 基于函数的索引要求等式匹配
1) 创建了基于函数的索引,但是如果执行下面的查询:
select * from emp where substr(ename,1,1)=’S’
得到的执行计划将还是(TABLE ACCESS FULL),因为只有当数据列能够等式匹配时,基于函数的索引才能生效,这样对于这种索引的计划和维护的要求都很高。请注意,向表中添加索引是非常危险的操作,因为这将导致许多查询执行计划的变更。然而,如果我们使用基于函数的索引就不会产生这样的问题,因为Oracle只有在查询使用了匹配的内置函数时才会使用这种类型的索引。
(十三) 决定使用全表扫描还是使用索引
1) 在大多数情况下,全表扫描可能会导致更多的物理磁盘输入输出,但是全表扫描有时又可能会因为高度并行化的存在而执行的更快。如果查询的表完全没有顺序,那么一个要返回记录数小于10%的查询可能会读取表中大部分的数据块,这样使用索引会使查询效率提高很多。但是如果表非常有顺序,那么如果查询的记录数大于40%时,可能使用全表扫描更快。因此,有一个索引范围扫描的总体原则是:
a) 对于原始排序的表 仅读取少于表记录数40%的查询应该使用索引范围扫描。反之,读取记录数目多于表记录数的40%的查询应该使用全表扫描。
b) 对于未排序的表 仅读取少于表记录数7%的查询应该使用索引范围扫描。反之,读取记录数目多于表记录数的7%的查询应该使用全表扫描。
随着时间的推移和数据的累计与变化,ORACLE对SQL语句的执行计划也会改变,比如:基于代价的优化方法,随着数据量的增大,优化器可能错误的不选择索引而采用全表扫描。这种情况可能是因为统计信息已经过时,在数据量变化很大后没有及时分析表;但如果对表进行分析之后,仍然没有用上合理的索引,那么就有必要对SQL语句用HINT提示,强制用合理的索引。但这种HINT提示也不能滥用,因为这种方法过于复杂,缺乏通用性和应变能力,同时也增加了维护上的代价;相对来说,基于函数右移、去掉“IN ,OR ,<>,IS NOT NULL ”、分解复杂的SQL语句等等方法,却是“放之四海皆准”的,可以放心大胆的使用。
相关推荐
*熟知安装oracle数据库软件的所有的相关知识及其步骤背后的意义。 *以oracle公司提供的建议为主、关系型数据库的理论为辅,学习oracle数据库的工作原理。 *真正熟悉sga的内涵,进而提升oracle服务器的性能。 *像协奏...
分区表理论知识........................41 1.3.2 普通表转分区表方法..................45 1.3.2.1 插入: Insert with a subquery method ...........................46 1.3.2.1.1 Oracle 11g 的...
本书包括数据库基本理论以及Oracle数据库系统知识两部分。主要包括关系模型基本理论,ER图及范式理论,SQL语言,Oracle存储空间的分配及释放时机,索引原理,事务处理及锁,备份恢复原理,存储过程及触发器,网络...
《Oracle11g宝典》以Oracle提供的示例数据库为背景,从基本原理、理论提高、实际操作、经验策略、应用开发等方面,结合命令行方式、开发工具的使用、管理工具的使用、Oracle与Windows之间的关系等知识点,按照学习...
1.3.1. 分区表理论知识 ................................................................ 1.3.2 普通表转分区表方法.......................................................... 1.3.2.1 插入: Insert with a ...
大多数书籍讲授的不是SQL本身,而是从数据库设计、规范化到关系数据库理论以及相关管理等所有内容。当然,这些内容都很重要,但并不是大多数仅想学习SQL的读者所感兴趣的。 因此,在找不到合适的书籍推荐给学生的...
轻举技术之“纲”,张合用之“目”,锻造SQL高可用性数据库应用指南从理论到实践,凝聚SQL主流数据库最前沿的技术要领,本书将深入浅出讨论。 本书特色:主要介绍SQL的语法规则及在实际开发中的应用,并且对SQL在...
《数据库原理及技术》课程设计 一、课程设计的目的和要求 (1)培养学生理解与《数据库原理》课程相关的理论知识,学会分析实际问题的能力。 (2)培养学生运用《数据库原理》相关知识设计系统应用的思想和方法。 ...
MYSQL基础理论知识 什么是数据库: 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。 数据库的类型: 关系型数据库:mysql—-mariaDB,oracle 非关系型数据库:nosql RDBMS 术语 数据库:是一些关联...
设计目的 " "(1)能运用所学"数据库原理及应用"以及"数据库设计与维护"课程的理论" "知识,分析并解决实际问题。 " "(2)掌握数据库设计的基本方法和步骤。 " "(3)掌握针对实际问题如何规划、管理和维护数据库的...
<br>目录 1、1字符串、字母表和语言 第一章 预备知识 1、2图和树 1、3归纳证明 1、4集合 1、5关系 1、6本书提要 2、1有穷状态系统 第二章 有穷自动机和正规表达式 2、2基本定义...
介绍了一些系统(如oracle、db2和informix等)中通用的新概念;对隔离技术作了更新介绍;对运行结果的表述更现代。相对于初始标准来说,sql数据库语言有了非常重要的变化,所以对对象关系给予特别讲述。本书还介绍了...
我们的报告不仅局限于理论讲解,还深入实际操作,展示如何使用常见的数据库管理系统,如MySQL、Oracle等,进行数据建模、表设计和查询优化。通过演示和实例分析,帮助您更好地理解和掌握数据库技术。 无论您是刚刚...
内容提要: Visual Foxpro是目前微机上流行采用了可视化的、面向对象的程序设计方法,大大简化了应用 系统的开发过程,本章是全书的基础,讨论了一些数据库系统的基础知识,为后面的学 习打下理论基础。主要从数据库...
应能反应出学生综 " "合利用Java Web知识与数据库知识完成一定得设计任务得能力,反映 " "出学生理论联系实践得动手能力。 " "具体要求如下: " "(1)明确所要开发系统得设计任务; " "(2)做好需求分析,合理...
"Web开发基于B/S架构的管理系统," " "20 "页面至少6个以上,应能反应出学 " " " "生综合利用Java " " " "Web知识和数据库知识完成一定的 " " " "设计任务的能力,反映出学生理论" " " "联系实践的动手能力。...
"Web开发基于B/S架构的管理系统, " " "20 "页面至少6个以上,应能反应出学生" " " "综合利用Java " " " "Web知识和数据库知识完成一定的 " " " "设计任务的能力,反映出学生理论 " " " "联系实践的动手能力....