oracle索引在in上优化,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
oracle 时间转换
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 > 0
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

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。