oracle索引

来源:互联网 发布:淘宝美工工具 编辑:程序博客网 时间:2024/06/11 16:16

简介

1.说明

  1)索引是数据库对象之一,用于加快数据的检索,类似于书籍的索引。在数据库中索引可以减少数据库程序查询结果时需要读取的数据量,类似于在书籍中我们利用索引可以不用翻阅整本书即可找到想要的信息。

  2)索引是建立在表上的可选对象;索引的关键在于通过一组排序后的索引键来取代默认的全表扫描检索方式,从而提高检索效率

  3)索引在逻辑上和物理上都与相关的表和数据无关,当创建或者删除一个索引时,不会影响基本的表;

  4)索引一旦建立,在表上进行DML操作时(例如在执行插入、修改或者删除相关操作时),oracle会自动管理索引,索引删除,不会对表产生影响

  5)索引对用户是透明的,无论表上是否有索引,sql语句的用法不变

  6)oracle创建主键时会自动在该列上创建索引

 

索引原理

1.  若没有索引,搜索某个记录时(例如查找name='wish')需要搜索所有的记录,因为不能保证只有一个wish,必须全部搜索一遍

2. 若在name上建立索引,oracle会对全表进行一次搜索,将每条记录的name值哪找升序排列,然后构建索引条目(name和rowid),存储到索引段中,查询name为wish时即可直接查找对应地方

3.创建了索引并不一定就会使用,oracle自动统计表的信息后,决定是否使用索引,表中数据很少时使用全表扫描速度已经很快,没有必要使用索引

 

索引使用(创建、修改、删除、查看)

1.创建索引语法

复制代码
CREATE [UNIQUE] | [BITMAP] INDEX index_name  --unique表示唯一索引ON table_name([column1 [ASC|DESC],column2    --bitmap,创建位图索引[ASC|DESC],…] | [express])[TABLESPACE tablespace_name][PCTFREE n1]                                 --指定索引在数据块中空闲空间[STORAGE (INITIAL n2)][NOLOGGING]                                  --表示创建和重建索引时允许对表做DML操作,默认情况下不应该使用[NOLINE][NOSORT];                                    --表示创建索引时不进行排序,默认不适用,如果数据已经是按照该索引顺序排列的可以使用
复制代码

2.修改索引

1)重命名索引

alter index index_sno rename to bitmap_index;

2) 合并索引(表使用一段时间后在索引中会产生碎片,此时索引效率会降低,可以选择重建索引或者合并索引,合并索引方式更好些,无需额外存储空间,代价较低)

alter index index_sno coalesce;

3)重建索引

  方式一:删除原来的索引,重新建立索引

  方式二:

alter index index_sno rebuild;

3.删除索引

drop index index_sno;

4.查看索引

select index_name,index-type, tablespace_name, uniqueness from all_indexes where table_name ='tablename'; -- eg:    create index index_sno on student('name');select * from all_indexes where table_name='student';

 

索引分类

1. B树索引(默认索引,保存讲过排序过的索引列和对应的rowid值)

1)说明:

  1.oracle中最常用的索引;B树索引就是一颗二叉树;叶子节点(双向链表)包含索引列和指向表中每个匹配行的ROWID值

  2.所有叶子节点具有相同的深度,因而不管查询条件怎样,查询速度基本相同

  3.能够适应精确查询、模糊查询和比较查询

2)分类:

   UNIQUE,NON-UNIQUE(默认),REVERSE KEY(数据列中的数据是反向存储的)

3)创建例子

craete index index_sno on student('sno');

 

4)适合使用场景:

  列基数(列不重复值的个数)大时适合使用B数索引

  

2. 位图索引

1)说明:

  1.创建位图索引时,oracle会扫描整张表,并为索引列的每个取值建立一个位图(位图中,对表中每一行使用一位(bit,0或者1)来标识该行是否包含该位图的索引列的取值,如果为1,表示对应的rowid所在的记录包含该位图索引列值),最后通过位图索引中的映射函数完成位到行的ROWID的转换

2)创建例子

create bitmap index index_sno on student(sno);

3) 适合场景:

对于基数小的列适合简历位图索引(例如性别等)

 

3.单列索引和复合索引(基于多个列创建)

1) 注意:

  即如果索引建立在多个列上,只有它的第一个列被where子句引用时,优化器才会使用该索引,即至少要包含组合索引的第一列

 

4. 函数索引

1)说明:

  1. 当经常要访问一些函数或者表达式时,可以将其存储在索引中,这样下次访问时,该值已经计算出来了,可以加快查询速度

  2. 函数索引既可以使用B数索引,也可以使用位图索引;当函数结果不确定时采用B树索引,结果是固定的某几个值时使用位图索引

  3. 函数索引中可以水泥用len、trim、substr、upper(每行返回独立结果),不能使用如sum、max、min、avg等

 

2)例子:

create index fbi  on student (upper(name));select * from student where upper(name) ='WISH';

 

索引建立原则总结

  1. 如果有两个或者以上的索引,其中有一个唯一性索引,而其他是非唯一,这种情况下oracle将使用唯一性索引而完全忽略非唯一性索引

  2. 至少要包含组合索引的第一列(即如果索引建立在多个列上,只有它的第一个列被where子句引用时,优化器才会使用该索引)

  3. 小表不要简历索引

  4. 对于基数大的列适合建立B树索引,对于基数小的列适合简历位图索引

  5. 列中有很多空值,但经常查询该列上非空记录时应该建立索引

  6. 经常进行连接查询的列应该创建索引

  7. 使用create index时要将最常查询的列放在最前面

  8. LONG(可变长字符串数据,最长2G)和LONG RAW(可变长二进制数据,最长2G)列不能创建索引

  9.限制表中索引的数量(创建索引耗费时间,并且随数据量的增大而增大;索引会占用物理空间;当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度)

  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将维护单个表列的索引(建立在单一表列上)或复合索引(建立在多个表列上)。复合索引称并置索引。


注意事项

1. 通配符在搜索词首出现时,oracle不能使用索引,eg:

复制代码
--我们在name上创建索引;create index index_name on student('name');--下面的方式oracle不适用name索引select * from student where name like '%wish%';--如果通配符出现在字符串的其他位置时,优化器能够利用索引;如下:select * from student where name like 'wish%';
复制代码

 

 2. 不要在索引列上使用not,可以采用其他方式代替如下:(oracle碰到not会停止使用索引,而采用全表扫描)

复制代码
select * from student where not (score=100);select * from student where score <> 100;--替换为select * from student where score>100 or score <100
复制代码

 

3. 索引上使用空值比较将停止使用索引, eg:

select * from student where score is not null;

二、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_typeexplain plan: sort order by table access full

  高效: (使用索引)select dept_code from dept where dept_type > 0explain 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 offset echo offset feedback offset pages 10000spool start_index_monitor.sql

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

spool offset heading onset echo onset feedback on

转:http://www.cnblogs.com/wishyouhappy/p/3681771.html
0 0