您的位置:首页 > 数据库 > Oracle

Oracle索引整理的详细描述

2010-09-08 15:42 253 查看

1.index需要储存空间和I/O操作。

2.index的目的是加快select的速度的。

3.insert,update,delete数据oracle会同时对索引进行相应的调整,因此会增加一定的消耗。

4.使用index一定能加快select速度吗?不是的,数据少和巨大时index会影响select的速度,因此如果查询速度可以满足,就不要建index。

5.Index 对null 无效。

 

分类:

一、从物理角度

1. partitioned or nonpartitioned : 分区或不分区索引。分区索引用于分区表。

2.B-tree(平衡树) : normal or reverse key 正常和倒序索引。

   oracle默认索引方式,平衡树形索引,在叶子节点上有双向链表,加快索引定位速度,oracle有一定的优化,可以根据链表直接定位记录,而不走树,综合使用提高速度。见图1和图2。

图1



 

 

图2



 

 

 

 

 

 

 

 

 

 

 

 

 

3.bitmap(位图)  :用二进制的0、1来构建索引,在进行or操作时非常快, 但要注意bitmap对于并发操作时,改一条会锁了很多记录,因为所有的记录在一个索引条目上,所以修改或增加时会一起锁定,见图3.

图3



 

 

区别和使用场景

B-tree索引

Bitmap 索引

Suitable for high-cardinality columns(记录对应的列重复的值较少,如主键,姓名等 )。

Suitable for low-cardinality columns(用在记录相同的值较多的列上,如果性别只有两种值:男和女)。

Updates on keys relatively inexpensive (在做updated时,b-tree只消耗很少的资源)。

Updates to key columns very expensive

(在做updated时,bitmap的消耗是昂贵的)。

Inefficient for queries using OR predicates(where子句中 or条件较多时速度较慢)

Effcient for queries using OR predicates

(where子句中 or条件较多时速度非常快)

Useful for OLTP(记录频繁的insert和update,查询相对较少的系统)。

Useful for data warehousing (OLIP)数据仓库,查询系统等较少做数据修改的系统。

 

 

二、逻辑角度:

1.single column or concatenated单索引和组合索引。

2.unique or nonunique: 唯一索引和非唯一索引。

3.function-based: 基于函数的索引,把一些where条件作为函数。

4.domain: 数据库以外的索引,如文件等。

 

 

三、创建index时的注意事项:

1.balance query and DML needs: 索引的目的是为了提高查询速度,但它会加重DML的负担。

2.place in separate tablespace: 索引和表应该放在不同的表空间,如果把索引和表放在同一个空间,会引起竞争,因为在读取一个表时,记录和索引是同时读取,修改也同步进行的。

3.use uniform extent sizes:Multipes of five blocks or minimum extent size for tablespace. 索引空间是extent是大小应该是5 blocks的倍数,因为oracle是一次读出5个blocks,如果你的extends是6,就会造成2次I/O操作。

4. consider nologging for large indexes: 在创建索引时可以关闭索引对应的redo 日志,提高速度,因为索引和数据不同,如果索引创建时出意外,数据还在,就再创建一次好了。

5.INITRANS should generally be higher on indexes than on the corresponding tables:INITRANS 参数比对应的表的值大些,因为索引也是已表记录的方式保存的,但索引大大小于表的记录,所以一个block中存储的索引记录就大大多于表在一个block中的记录,加大INITRANS可以增加在一个block中的事务的并发数,就提高了效率。

6.rebuilding indexes:如果删除一条记录,对应的索引仅仅是做了逻辑删除,只有一个block中的全部索引都被标识为逻辑删除,orcle才会真正的回收block, 这时这个block才能被再次利用,在表的记录做update时,index是先做了逻辑删除,然后再为该记录新建一个索引的,所以表在频繁的增删改后,就会造成index对应的block不完整,和系统碎片的情况是一致的,造成空间浪费,加大index的I/O,影响性能。而rebuilding indexes就可以回收原来的,重新构建一个高效的索引,但重构时会锁表。

              语法: alter index index_name rebuild;

7. coalescing indexes: 整理索引碎片,效率高,不锁表。

语法:Alter index  index_name coalesce;

 

四.管理索引

1.分析索引:

1) select * from user_objects where object_type='INDEX'

2)analyze index PK_T_TICKET validate structure;

3)select * from index_stats;

HEIGHT(b-tree的高度)

BLOCKS(索引有多少块)

NAME(索引名)

LF_ROWS(记录数)

DEL_LF_ROWS(删除记录数)

2

256

PK_T_TICKET

82775

792

当 DEL_LF_ROWS/ LF_ROWS>15%时应进行 索引重建或 索引碎片整理。

 

2.drop 索引:当屁量导入大量数据时,索引会影响导入速度。可以现在drop掉,导入后再重建索引。

 

3.监控索引:

    1)设置监控那个索引 alter index pk_t_ticket monitoring usage;

2)查看该索引用没有使用select * from v$object_usage

3)select count(1) from pk_t_ticket;

4) 查看该索引用没有使用select * from v$object_usage

5)关闭监控 alter index pk_t_ticket nomonitoring usage;

监控一个月就大概可以知道那些是无用的索引了。

6) 查询索引的详细信息 : select * from all_ind_columns where index_name='PK_T_TICKET' .那个表的那个列上有索引及详细信息。

---------------------------------------------------------------------------------------

以下的文章主要是对Oracle索引整理的描述,其中包含了Oracle的索引陷阱,以及各种索引使用场合以及建议,还有能用唯一索引,一定用唯一索引有哪些的详细内容的介绍,以下就好似相关内容的介绍。
一、Oracle的索引陷阱
一个表中有几百万条数据,对某个字段加了索引,但是查询时性能并没有什么提高,这主要可能是Oracle的索引限制造成的。
Oracle的索引有一些索引限制,在这些索引限制发生的情况下,即使已经加了索引,Oracle还是会执行一次全表扫描,查询的性能不会比不加Oracle索引有所提高,反而可能由于数据库维护索引的系统开销造成性能更差。
下面是一些常见的索引限制问题。
1、使用不等于操作符(<>, !=)
下面这种情况,即使在列dept_id有一个索引,查询语句仍然执行一次全表扫描

select * from dept where staff_num <> 1000;
复制代码

但是开发中的确需要这样的查询,难道没有解决问题的办法了吗?
有!
通过把用 or 语法替代不等号进行查询,就可以使用Oracle索引,以避免全表扫描:上面的语句改成下面这样的,就可以使用索引了。

select * from dept shere staff_num < 1000 or dept_id > 1000;
复制代码

2、使用 is null 或 is not null
使用 is null 或is nuo null也会限制索引的使用,因为数据库并没有定义null值。如果被索引的列中有很多null,就不会使用这个索引(除非索引是一个位图索引,关于位图索引,会在以后的blog文章里做详细解释)。在sql语句中使用null会造成很多麻烦。
解决这个问题的办法就是:建表时把需要索引的列定义为非空(not null)
3、使用函数
如果没有使用基于函数的索引,那么where子句中对存在Oracle索引的列使用函数时,会使优化器忽略掉这些索引。下面的查询就不会使用索引:

select * from staff where trunc(birthdate)

= '01-MAY-82';
复制代码

但是把函数应用在条件上,索引是可以生效的,把上面的语句改成下面的语句,就可以通过索引进行查找。

select * from staff where birthdate <

(to_date('01-MAY-82') + 0.9999);
复制代码

4、比较不匹配的数据类型
比较不匹配的数据类型也是难于发现的性能问题之一。
下面的例子中,dept_id是一个varchar2型的字段,在这个字段上有Oracle索引,但是下面的语句会执行全表扫描。

select * from dept where dept_id = 900198;
复制代码

这是因为Oracle会自动把where子句转换成to_number(dept_id)=900198,就是3所说的情况,这样就限制了索引的使用。
把SQL语句改为如下形式就可以使用索引

select * from dept where dept_id = '900198';
复制代码

二、各种索引使用场合及建议
(1)B*Tree索引。
常规索引,多用于oltp系统,快速定位行,应建立于高cardinality列(即列的唯一值除以行数为一个很大的值,存在很少的相同值)。

Create index indexname on tablename(columnname[columnname...])
复制代码

(2)反向Oracle索引。
B*Tree的衍生产物,应用于特殊场合,在ops环境加序列增加的列上建立,不适合做区域扫描。

Create index indexname on tablename

(columnname[columnname...]) reverse
复制代码

(3)降序索引。
B*Tree的衍生产物,应用于有降序排列的搜索语句中,索引中储存了降序排列的索引码,提供了快速的降序搜索。

Create index indexname on tablename(columnname DESC[columnname...])
复制代码

(4)位图索引。
位图方式管理的索引,适用于OLAP(在线分析)和DSS(决策处理)系统,应建立于低cardinality列,
适合集中读取,不适合插入和修改,提供比B*Tree索引更节省的空间。

Create BITMAP index indexname on tablename(columnname[columnname...])
复制代码

在实际应用中,如果某个字段的值需要频繁更新,那么就不适合在它上面创建位图索引。
在位图Oracle索引中,如果你更新或插入其中一条数值为N的记录,
那么相应表中数值为N的记录(可能成百上千条)全部被Oracle锁定,
这就意味着其它用户不能同时更新这些数值为N的记录,其它用户必须要等第一个用户提交后,
才能获得锁,更新或插入数据,bitmap index它主要用于决策支持系统或静态数据。
(5)函数索引。
B*Tree的衍生产物,应用于查询语句条件列上包含函数的情况,
索引中储存了经过函数计算的索引码值。可以在不修改应用程序的基础上能提高查询效率。
索引创建策略
1.导入数据后再创建索引
2.不需要为很小的表创建索引
3.对于取值范围很小的字段(比如性别字段)应当建立位图索引
4.限制表中的索引的数目
5.为索引设置合适的PCTFREE值
6.存储索引的表空间最好单独设定
唯一索引和不唯一索引都只是针对B树索引而言.
Oracle最多允许包含32个字段的复合Oracle索引
由此估计出一个查询如果使用某个索引会需要读入的数据块块数。
需要读入的数据块越多,则 cost 越大,Oracle 也就越有可能不选择使用 index
三、能用唯一索引,一定用唯一索引
能加非空,就加非空约束
一定要统计表的信息,索引的信息,柱状图的信息。
联合索引的顺序不同,影响Oracle索引的选择,尽量将值少的放在前面
只有做到以上四点,数据库才会正确的选择执行计划。
保留原文链接:http://bbs.chinabyte.com/thread-383132-1-1.html

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: