Oracle调优----调优索引

目标:

1.索引的类型

2.使用索引的有点

3.索引扫描类型

4.为什么不使用索引

5.怎样使用索引

6.创建索引的原则

一、索引的类型

1.B树索引  常用

2.位图索引   常用

3.HASH索引

4.索引组织表IOT

5.反转键(reverse keys)索引

6.基于函数的索引 常用

7.分区索引(本地索引、全局索引)

8.位图连接索引

----B树索引

B树索引在Oracle中是一个通用索引,创建索引的时候默认就是B树索引。

B树索引分为单列索引和组合索引(最多可以多达32个列);

对于B树索引,我们需要关注他的二元高度(blevel);

B树索引保存了索引列上有值的每个数据行的ROWID.

Oracle不会对索引列上包含NULL值得行进行索引,如果索引是一个组合索引,二其中有一列不为空,这一行会于索引列中;


-------位图索引


对于位图索引的列,列值的数量要求较少或者中等(索引列技术较小)

对于较低技术的位图索引来说,位图索引的尺寸远远的小于B树索引,因此可以大大的减少IO的数量。

对于非常大的表来说,在多个低基数列上建立位图索引是一个很好的选择。

对于位图索引来说,即使从表中读取很多行,也会使用位图索引。

例如在一个sex 列上建立索引,每次从表中读取板书的数据行,但是还是会使用位图索引。

---B树索引和位图索引的比较

在B树索引中,可以实现行级锁定,但是在位图索引中,因为对ROWID进行压缩存放(一个ROWID范围+位图),因此每次所内的都是ROWID范围,因此对表中的位图索引列进行更新的时候,并发性很差,很容易导致死锁,SELECT语句不会受到这种锁定问题的影响;

注意:不要在繁忙的OLTP系统中使用位图索引;


-----反转索引

当载入一些有序的数据时,索引肯定会碰到与IO相关的一些瓶颈。在载入期间,某部分索引和磁盘肯定会比掐部分使用拼房到的多。

为了解决这个为题,我们可以使用反转索引,这样对于有序数据的载入,Oracle会更新不同的索引块。

1234、1235、1236,如果数据以反转索引存储,那么这些数据的存放形式为4321,5321,6321.结果就是索引会为索引会每次新插入的行更新不同的索引块。


创建反转索引:

create unique index i1_t1 on t1(c1)
reverse pctfree 30
storage(initial 200k next 200k pctincrease o maxextents 50)tablesapce index;

create unique index i2_t1 on ()t1(c2)
alter index i2_t1 rebuild reverse;

------基于函数的索引

create index fbi_upper_lastname on customers(upper(cust_last_name))

select * from customers where upper (cust_last_name)='SMITH'

基于函数的索引需要考虑的问题

1.基于函数的索引只能针对一种函数,对于其余的函数不骑作用

2.控制索引的数量,因为对DML(数据操纵语言)会产生影响

基于函数的索引会带来极大的好处

-----分区索引

分区索引就是简单的吧一个索引分成多个片段,这样可以访问更小的片段,可以将片段分别放在不同的磁盘驱动器上。

B树索引和位图索引都可以被分区,而hash索引不能被分区。

几种分区方式:

1.表被分区二索引未被分区

2.表未被分区二索引被分区

3.表和索引都被分区

无论那种方式,都必须使用基于成本的优化器。

分区可以提高性能和可维护性。

二、索引的优点

1.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

2.可以大大加快数据的检索速度,这也是创建索引的最主要原因

3.可以加速表和表之间的连接,特别是实现数据的参考完整性方面特别有意义

4.在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间

5.通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能

三、索引扫描类型

根据索引的类型和where条件的限制不同,有五种索引扫描类型:

1.索引唯一扫描(INDEX UNIQUE SCAN)

2.索引范围扫描(INDEX RANGE SCAN)

3.索引全扫描(INDEX FULL SCAN)

4.索引快速扫描(INDEX FAST FULL SCAN)

5.索引跳跃扫描(INDEX SKIP SCAN)

--索引唯一扫描

通过唯一键、主键,Oracle通常放回一个数据行,因此采用的是索引唯一扫描


---索引范围扫描

1.在唯一键上使用range操作符(>,<,<>,>=,<=,between)

2.在组合索引上,只使用部分列进行查询、导致查询多行

3.对非唯一索引列上进行的查询

---索引全扫描

差存储的数据必须从全部所以那种得到

---快速全索引扫描

在索引的快速全局扫描期间,Oracle读取B书索引上的所有树叶块,这个索引可以按照顺序读取,这样可以一次性读取多个块,初始化文件中的DB_FILE_MULTIBLOCK_READ_COUNT可以控制同时被读取的块数。

相对全表扫描,快速全局索引扫描通常需要较少的物理IO。

如果表查询的所有列都被包含在索引中,而索引的前置两列并不在where条件中,那么就可以使用快速全局索引扫描。

select empno,ename,deptno form emp where deptno=30; empno,ename,deptno上有一个组合索引

作为一个选择,针对上面的情况,Oracle可能采取跳跃式索引扫描。

---跳跃式索引扫描

组合索引、where条件中没有出现前置列(通常是组合索引的第二列)

相对全索引扫描,跳跃式索引扫描读取的数据块更少、速度更快。


四、索引限制

我们来研究下使用where但是阻止Oracle使用索引的集中情况

1.使用不等于运算符(<>,!=)

explain plan for select * from abc where xinbie<>1;
select * from table(dbms_xplan.display);

2.使用is null或使用is not null

在where子句中使用is null或者is not null同样会限制索引的使用。

如果被索引的列在某些行中存在null值,在索引列中就不会有相应的条目。

(例外:位图索引中对于null列也会进行记录,因为此位图索引对于null搜索通常较为快速)

3.使用函数

如果不使用基于函数的索引,那么在SQL语句中where自己中对存在索引的列使用函数时,会使优化器忽略掉这些索引

一些常见的函数:trunc,substr,to_date,to_char,instr等,都可能会使索引失效

解决方案:

①使用基于函数的索引 

②灵活书写SQL、避免在索引列上使用SQL函数

4.比较不匹配的数据类型

这个是比较难于发现的问题。Oracle不会对不匹配的数据类型报错,Oracle会隐式的吧varchar2列的数据类型转换成要被比较的数值类型(举例,还存在其他的数据类型转换)

select bank_name,address,city,state,zip from banks where account_number=990354
Oracle可以自动把where子句变成to_number(account_number)=990354

五、索引的选择性

Oracle通过多种方法来判断使用索引的价值,第一个方法是判断索引中的胃一直和不同建的数量

唯一键的数量/表的行数,判断索引的选择性。


六、集群因子(cluster factor)

集群因子是索引与他所基于的表想比较得出的有序性度量,它用于检查在索引访问之后执行的表查找的成本(将集群因子与选择性相乘即可的到该操作的成本)。

Custering Factor的含义:如果通过一个索引扫描一张表,需要访问的表的数据块的数量。

Custering Factor计算的方法如下:

1.扫描一个索引

2.比较某行的rowid和前一行的rowid,如果这两个rowid不属于同一个数据块,那么cluster factor增加1

3.整个索引扫描完毕后,就得到了该索引的cluster factor。如果Clustering Factor接近于表存储的块数,说明这张表是按照索引字段你的顺序存储的,如果Clustering Factor接近于行的数量,那说明这张表不是按照索引字段顺序存储的。

在计算索引访问成本的时候,这个值十分有用。Clustering Factor乘以选择性参数(selectivity)就是访问索引的开销。

如果这个统计数据不能真实反映出索引的真实情况,那么可能曹成优化器错误的选择执行计划。

另外如果某张表上的大多数访问时按照某个索引做索引扫描,那么僵该表的数据按照索引字段的顺序从新组织,可以提高该表的访问性能。

select index_name,table_name,clustering_factor from dba_indexes where table_name='abc';
select segment_name,blcoks from dba_segments where segment_name='abc';
select AUG_ROW_LEN from dba_tables where table_name='abc';
select count(*) from emr.abc;

聚集因子的数量和表的块数一直,因此表的数据排序和索引一致,因此在进行索引范围扫描ode时候,对表的访问成本还是比较低的。

狙击因子主要影响的是索引范围扫描。

如果聚集因子很高,那么建议对表进行重新整理,减低聚集。

七、二元高度(binary height)

索引查找分为两个过程:

1.根据树进行定位、找出rowid(索引查找)

2.根据rowid找出表中的数据行(表数据查找)

索引:进行索引查找的时候,首先从树根开始读数据,通过中间表节点,最后定位到叶节点,整个过程只能进行行但数据块的读取;

如下:二元高度是3,读取一行数据经过了三次数据块的读取,其中三次是索引,一次是表数据。


select blevel,index_name from user_indexes where index_name='EMP_DEPATMENT_IX';
查找每个索引的二元高度,这个索引值占用了1个数据块,因此二元高度是0;

二元高度随着表中索引列的非NULL值以及索引列中值的宽度而变化。

如果索引列上大量的行被删除,那么他的二元高度不会降低,重建索引会降低二元高度,如果一个索引中被删除的行接近20%~25%,重建索引会降低二元高度。

二元高度对索引的性能影响不是很大,但是在可能的情况下,降低二元高度还是有必要的。

八、使用直方图

在分析表和索引时,直方图用户记录数据的分布。

通过获取该信息,基于成本的优化器就可以决定使用量返回少量行的索引,而避免使用基于限制条件返回许多行的索引。

直方图的使用不受索引的限制,我们可以在表的任何列上构建直方图(一般是在表的索引列上构建直方图)

构建直方图最主要的原因就是:帮助优化器在表中数据严重倾斜时做出更好的规划。

如果一个表中的列上(通常是索引列)数据放生严重的倾斜,那么在这个列上建立直方图将非常的有意义。这样优化器就知道什么时候该使用索引、什么时候不该使用索引。

exec dbms_stats.gather_table_stats('hr','emrloyees',method_opt=>'for columns size 10 job_id');
在hr用户下面的employees表的job_id列上建立了一个直方图,这个直方图有10个存储桶;

对整个列的100行数据进行均分成10个存储桶,每个同种存储10个数据行。然后写出每个桶中的数据范围。

我们发现1430这个数值对应的行号数非常多,大约73行,找到了73%,因此当我们使用 where id=1403的时候,优化器就不会走索引,默认情况下,Oracle的直方图会长胜75的存储桶,可以把存储桶的size限制在1~254之间

九、其他

创建查询:指导原则

1.平衡查询和DML需求

2.存储在独立的表空间中

3.使用同一的片大小:5个块的整数倍或者表空间的MINIMUN EXTENT

4.对于巨型索引,考虑NOLOGGING

5.INITRANS应该设得比相应的表要高一些

索引的联机重构

在重构索引时,可以使用最少的表锁

alter index orders_id_idx rebuild online;

鉴别不使用的索引:

1.开始检测一个索引的使用

alter index summit.orders_id_idx monitoring usage;

2.停止对一个索引的检测

alter index summit.orders_id_idx nomonitoring usage;

创建索引的原则:

1.在OLTP系统中,索引尽量少创建;

2.在OLTP系统中对拼房更新的表不要创建位图索引;

3.在经常存取的所以一个列上不要建立符合索引,但要注意符合索引的建立顺序要按照使用的频度来确定;

4.如果where语句中不得不对查询列采用函数查询,如upper函数,最好建立相应的函数索引;

5.用于连接的列(主外键)上建立索引;

6.在SQL语句中经常进行group by、order by的字段上建立索引;

获取索引信息:

通过查询数据字典获取有关索引的信息。

①DBA_INDEXES:提供索引的信息

②DBA_IND_COLUMNS:提供索引字段的信息

③DBA_IND_EXPRESSIONS:提供基于函数的索引信息

④V$OBJECT_USAGE:提供了索引的使用信息





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值