Oracle中索引的使用 索引性能优化调整

索引是由Oracle维护的可选结构,为数据提供快速的访问。准确地判断在什么地方需要使用索引是困难的,使用索引有利于调节检索速度。
当建立一个索引时,必须指定用于跟踪的表名以及一个或多个表列。一旦建立了索引,在用户表中建立、更改和删除数据库时,
Oracle就自动地维护索引。创建索引时,下列准则将帮助用户做出决定: 
      
1)
索引应该在SQL语句的"where"或"and"部分涉及的表列(也称谓词)被建立。假如personnel表的"firstname"表列作为查询结果显示,而不是作为谓词部分,则不论其值是什么,该表列不会被索引。 
      
2) 用户应该索引具有一定范围的表列,索引时有一个大致的原则:如果表中列的值占该表中行的2 0 %以内,这个表列就可以作为候选索引表列。假设一个表有36
000行且表中一个表列的值平均分布(大约每12000行),那么该表列不适合于一个索引。然而,如果同一个表中的其他表列中列值的行在1 0 0 0~1 5 0
0之间(占3 %~4 %
),则该表列可用作索引。 

      
3)如果在S Q L语句谓词中多个表列被一起连续引用,则应该考虑将这些表列一起放在一个索引内, O r a c l
e将维护单个表列的索引(建立在单一表列上)或复合索引(建立在多个表列上)。复合索引称并置索引。 

一、主关键字的约束 

  关系数据库理论指出,在表中能唯一标识表的每个数据行的一个或多个表列是对象的主关键字。由于数据字典中定义的主关键字能确保表中数据行之间的唯一性,因此,在O
r a c l e 8
i数据库中建立表索引关键字有助于应用调节。另外,这也减轻了开发者为了实现唯一性检查,而需要各自编程的要求。 

  提示使用主关键字索引条目比不使用主关键字索引检索得快。 

  假设表p
e r s o n把它的i d表列作为主关键字,用下列代码设置约束: 
alter table person add
constraint person_pk primary key (id) using index storage (initial 1m next 1m
pctincrease 0) tablespace prd_indexes ; 

  处理下列S Q
L语句时:select last_name ,first_name ,salary from person where id = 289


  在查找一个已确定的“ i d”表列值时, O r a c l e将直接找到p e r s o n _
p k。如果其未找到正确的索引条目,O r a c l
e知道该行不存在。主关键字索引具有下列两个独特之处: 

 1.1因为索引是唯一的, 所以O r a c l
e知道只有一个条目具有设定值。如果查找到了所期望的条目,则立即终止查找。 

 1.2一旦遇到一个大于设定值的条目,索引的顺序搜索可被终止; 

二、ORDER
BY中用索引 

  ORDER BY
子句只在两种严格的条件下使用索引. 
  ORDER
BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序. 
  ORDER
BY中所有的列必须定义为非空. 
  WHERE子句使用的索引和ORDER
BY子句中所使用的索引不能并列. 

例如: 
  表DEPT包含以下列: 
dept_code
pk not null 
dept_desc not
null 
dept_type
null 

非唯一性的索引(dept_type)

  低效: (索引不被使用) 
select dept_code
from dept order by dept_type 
explain plan: sort order by
table access full 

  高效:
(使用索引) 
select dept_code from dept where dept_type >

explain plan: 
table access by
rowid on emp 
index range scan on
dept_idx 

三、避免改变索引列的类型 

  当比较不同数据类型的数据时,
oracle自动对列进行简单的类型转换. 

假设
empno是一个数值类型的索引列: 
  select …from emp where empno =
‘123‘ 
  实际上,经过ORACLE类型转换, 语句转化为: select … from emp where
empno =
to_number(‘123‘) 

  幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变. 

  现在,假设emp_type是一个字符类型的索引列:
select … from emp where emp_type = 123 
  这个语句被oracle转换为:
select … from emp where
to_number(emp_type)=123 

  因为内部发生的类型转换, 这个索引将不会被用到!
为了避免oracle对你的sql进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时,
oracle会优先转换数值类型到字符类型. 

四、需要当心的where子句 

某些select
语句中的where子句不使用索引. 这里有一些例子: 

1、IS NULL 与 IS NOT
NULL 
  不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。 
  任何在where子句中使用is
null或is not null的语句优化器是不允许使用索引的。 

2、‘!=‘ 将不使用索引. 记住,
索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中 

不使用索引: select * from
employee where salary<>3000; 
使用索引: select
account_name from transaction where amount >0; 
使用索引:
select * from employee where salary<3000 or
salary>3000; 

3、联接列,‘||‘是字符连接函数. 就象其他函数那样,
停用了索引 

不使用索引: select account_name,amount from
transaction where
account_name||account_type=‘AMEXA‘; 
使用索引: select
account_name,amount from transaction where account_name = ‘AMEX‘ and
account_type=‘ A‘; 

4、‘+‘是数学函数. 就象其他数学函数那样,
停用了索引 

不使用索引: select account_name, amount from
transaction where amount + 3000 >5000; 
使用索引: select
account_name, amount from transaction where amount > 2000


5、相同的索引列不能互相比较,这将会启用全表扫描 

不使用索引:
select account_name, amount from transaction where account_name =
nvl(:acc_name,account_name); 
使用索引: select account_name,
amount from transaction where account_name like
nvl(:acc_name,‘%‘); 

6、带通配符(%)的like语句 

不使用索引:
select * from employee where last_name like
‘%cliton%‘; 
使用索引: select * from employee where last_name
like ‘c%‘ 

7、IN和EXISTS 

不使用索引:
... where column in(select * from ... where ...); 
使用索引:
... where exists (select ‘X‘ from ...where
...); 
同时应尽可能使用NOT EXISTS来代替NOT
IN,尽管二者都使用了NOT(不能使用索引而降低速度),NOT EXISTS要比NOT
IN查询效率更高。 

如果一定要对使用函数的列启用索引: 
1、oracle新的功能:
基于函数的索引(function-based index) 也许是一个较好的方案: 
create index
emp_i on emp (upper(ename)); /*建立基于函数的索引*/ 
select * from
emp where upper(ename) = ‘BLACKSNAIL‘; /*将使用索引*/ 
2、MS SQL
Server显示申明指定索引: 
SELECT * FROM PersonMember (INDEX =
IX_Title) WHERE processid IN
(‘男‘,‘女‘) 

五、怎样监控无用的索引 

  Oracle
9i以上,可以监控索引的使用情况,如果一段时间内没有使用的索引,一般就是无用的索引 

  语法为: 
  开始监控:alter
index index_name monitoring usage; 
  检查使用状态:select * from
v$object_usage; 
  停止监控:alter index index_name nomonitoring
usage; 
  当然,如果想监控整个用户下的索引,可以采用如下的脚本: 

set
heading off 
set echo off 
set
feedback off 
set pages 10000 
spool
start_index_monitor.sql 

SELECT ‘alter index
‘||owner||‘.‘||index_name||‘ monitoring usage;‘ FROM dba_indexes WHERE owner =
USER; 

spool off 
set heading
on 
set echo on 
set feedback
on 
------------------------------------------------------------------------------------------------------------------------------ 
set
heading off 
set echo off 
set
feedback off 
set pages 10000 
spool
stop_index_monitor.sql 

SELECT ‘alter index
‘||owner||‘.‘||index_name||‘ nomonitoring usage;‘ FROM dba_indexes WHERE owner =
USER; 

spool off 
set heading
on 
set echo on 
set feedback
on

原文:http://czllfy.iteye.com/blog/510282

时间: 2024-11-01 18:23:23

Oracle中索引的使用 索引性能优化调整的相关文章

【转】Oracle Freelist和HWM原理及性能优化

文章转自:http://www.wzsky.net/html/Program/DataBase/74799.html 近期来,FreeList的重要作用逐渐为Oracle DBA所认识,网上也出现一些相关的讨论.本文以FreeList为线索对Oracle的存储管理的原理进行较深入的探讨,涉及Oracle段区块管理的 原理,FreeList算法等.而与FreeList密切相关的一个重用特性HWM,与sql性能密切相关,本文也作了原理分析介绍.在原理探讨的基础 上,介绍了常用的存储参数分析方法,并对

MySQL索引使用方法和性能优化

关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车.对于没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型网站单日就可能会产生几十万甚至几百万的数据,没有索引查询会变的非常缓慢.还是以WordPress来说,其多个数据表都会对经常被查询的字段添加索引,比如wp_comments表中针对5个字段设计了BTREE索引. 一个简单的对比测试 以我去年测试的数据作为一个简单示例,20多条数据源随机生成200万条

oracle中数据的分页显示及优化

在一个页面中经常会出现分页的现象,那么后台数据库又应该如何分页显示呢? 分页可以使用oracle中的rownum函数. 一个页面中从第几行到第几行数据的显示. 下面以scott用户下的emp表说明: 语句一: select b.* from( select a.* ,rownum row_num from (select * from emp ) a) bwhere row_num between 3 and 5; 语句二: select b.* from( select a.* ,rownum

Atitit 如何利用先有索引项进行查询性能优化

1.1. 再分析的话就是我们所写的查询条件,其实大部分情况也无非以下几种:1 1.2. 范围查找 动态索引查找1 1.2.1. 索引联合 所谓的索引联合,就是根据就是根据筛选条件的不同,拆分成不同的条件,去匹配不同的索引项.2 1.3. 索引交叉2 1.1. 再分析的话就是我们所写的查询条件,其实大部分情况也无非以下几种: 1.等于谓词:select [email protected] 2.比较谓词:select ...where...column> or < or  <> or

oracle中查询用户表/索引/视图创建语句

不多说,直接上干货 1.查询当前用户下表的创建语句 select dbms_metadata.get_ddl('TABLE','ux_future') from dual; 2.查询其他用户下表的创建语句 select dbms_metadata.get_ddl('TABLE','ux_future','Admin') from dual; 3.查询当前用户下索引的创建语句 select dbms_metadata.get_ddl('INDEX','ux_future') from dual;

oracle中提高order by的性能

1.如果order by columnA,那么在where查询条件中添加条件columnA=value,则oracle内部会过滤order by排序,直接用索引. 2.如果order by columnA,columnB,那么在where查询条件中添加条件columnA=value1,columnB=value1,则oracle内部会过滤order by排序,直接用索引. 3.如果order by columnA,但是在where查询条件中没有columnA=value,那么在查询的时候添加hi

论mysql5.7.13性能优化之索引优化

防伪码:吾日三省吾身 一.MySQL 性能优化之-影响性能的因素 1. 商业需求的影响 不合理需求造成资源投入产出比过低,这里我们就用一个看上去很简单的功能来分析一下. 需求:一个论坛帖子总量的统计,附加要求:实时更新 从功能上来看非常容易实现,执行一条 SELECT COUNT(*) from 表名的 Query 就可以得到结 果.但是,如果我们采用不是 MyISAM 存储引擎,而是使用的 Innodb 的存储引擎,那么大 家可以试想一下,如果存放帖子的表中已经有上千万的帖子的时候,执行这条

数据库性能优化一:SQL索引一步到位

SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱. 1.1 什么是索引? SQL索引有两种,聚集索引和非聚集索引,索引主要目的是提高了SQL Server系统的性能,加快数据的查询速度与减少系统的响应时间 下面举两个简单的例子: 图书馆的例子:一个图书馆那么多书,怎么管理呢?建立一个字母开头的目录,例如:a开头的书,在第一排,b开头的在第二排,这样在找什么书就好说了,这个就是一个聚集索引,可是很多人借书找某某

Oracle中组合索引的使用详解(转)

在Oracle中可以创建组合索引,即同时包含两个或两个以上列的索引.在组合索引的使用方面,Oracle有以下特点: 1. 当使用基于规则的优化器(RBO)时,只有当组合索引的前导列出现在SQL语句的where子句中时,才会使用到该索引: 2. 在使用Oracle9i之前的基于成本的优化器(CBO)时, 只有当组合索引的前导列出现在SQL语句的where子句中时,才可能会使用到该索引,这取决于优化器计算的使用索引的成本和使用全表扫描的成本,Oracle会自动选择成本低的访问路径(请见下面的测试1和