Oracle性能分析6:数据访问方式之索引扫描

这节将介绍各种索引扫描方式,在了解了各种索引扫描方式的特点后,你就可以判断你的执行计划中使用的扫描方式是否正确,并可以针对获取的信息作出改进。

索引唯一扫描

在下面的场景中使用相等条件时,数据库使用索引唯一扫描。

1)查询条件中包含唯一索引中的所有列时;

2)查询条件使用主键约束列时。

下面是一个实际的例子,在表historyalarm中创建如下唯一索引:

create unique index idx_historyalarm$queryid on historyalarm(queryid) tablespace uep4x_fm_index

然后在表上执行查询:

select * from historyalarm where queryid = 3

该查询符合上面的第一种情况,会使用索引唯一扫描,该查询的执行计划如下:

	DESCRIPTION							OBJECT NAME
-----------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS
 TABLE ACCESS BY GLOBAL INDEX ROWID		HISTORYALARM
  INDEX UNIQUE SCAN						IDX_HISTORYALARM$QUERYID

这里Oracle首先通过唯一索引扫描找到索引节点,然后使用索引节点中包含的rowid来访问表中的数据。

索引范围扫描

当查询条件可能会返回一定范围的数据时就会选用索引范围扫描,索引可以是唯一索引或者不唯一索引,但如果查询条件包含的数据范围太大,也有可能导致全表扫描。查询条件中使用<、>、LIKE、BETWEEN、=等都可能使用索引范围扫描,需要注意单个=条件在唯一索引或者主键上将导致索引唯一扫描。

下面是一个索引范围扫描的例子,在上面的histroyalarm中执行一个范围查询:

select * from caffm4x.historyalarm where queryid < 10

这里查询的数据是一个范围,且使用了queryid列,在queryid列上有唯一索引,但任然会导致索引范围扫描:

	DESCRIPTION							OBJECT NAME
-----------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS
 TABLE ACCESS BY GLOBAL INDEX ROWID		HISTORYALARM
  INDEX RANGE SCAN						IDX_HISTORYALARM$QUERYID

索引范围扫描从索引的根节点出发,找到第一个匹配的条目所在的叶子数据块开始遍历索引结构,首先从索引条目中取出rowid然后取出对应的表数据块(通过rowid访问数据表),接下来叶子索引块会被再次访问并读取下一个索引条目并获取rowid,这样反复直到整个叶子索引块被的索引条目全部被读出。因此排除索引根节点和中间节点,每行数据读取需要读取两个数据块,我们可以通过blevel来得到索引高度,通过索引高度和获取的数据行数就能得到需要读取的数据块数,例如:如果blevel为3,读取5行数据,则总的需要访问的数据块次数将是(5*2)
+ 3 = 13(注意只有根节点时blevel为0)。

如果在读取了整个叶子索引块之后,还需要访问下一个叶子索引块,在当前的叶子索引块中有指向下一个叶子索引块的指针(也含有指向上一个叶子索引块的指针)。

使用索引范围扫描的另一个优势就在于排序,由于索引的节点是有序的,因此如果查询的结果需要按照索引列排序(升序或者降序),那么使用索引范围扫描则可以很好的避免排序操作,例如:

select * from historyalarm where queryid > 10

由于queryid大于10的数据量占总数据量的99%,因此Oracle的优化器选择了全表扫描:

	DESCRIPTION							OBJECT NAME
-----------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS
 PARTITION RANGE ALL
  TABLE ACCESS FULL						HISTORYALARM

如果我们在查询时对数据指定排序,如下:

select * from historyalarm where queryid > 10 order by queryid

执行计划如下:

	DESCRIPTION							OBJECT NAME
-----------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS
 TABLE ACCESS BY GLOBAL INDEX ROWID		HISTORYALARM
  INDEX RANGE SCAN						IDX_HISTORYALARM$QUERYID

优化器改为使用了索引范围扫描。由于当数据量很大时,排序的代价是很大的(可能导致物理排序),这时使用索引范围扫描将是一个很好的选择,特别是当你排序后选择部分数据的情况下(rownum < n)。

索引全扫描

索引全扫描会读取索引上的所有条目,下面几种情况可能导致索引全扫描:

1)没有条件但是所需获取列的列表可以通过其中一列的索引来获得;

select id from t3

	DESCRIPTION							OBJECT NAME
-----------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS
 INDEX FULL SCAN						IDX_T3_ID

由于id列带有索引,因此这里优化器选择了索引全扫描。

2)查询条件中包含排序操作

select * from historyalarm order by queryid

	DESCRIPTION							OBJECT NAME
-----------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS
 INDEX FULL SCAN						IDX_HISTORYALARM$QUERYID

索引全扫描读取单个数据块,读取每个条目的rowid,再通过rowid取出数据行,由于索引已经排序,所以不必执行排序操作。如果查询只请求了索引列,数据库将跳过表访问,只通过访问索引得到数据。

索引全扫描的另一个优势在计算最大、最小值时:

select min(queryid) from historyalarm 

	DESCRIPTION							OBJECT NAME
-----------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS
 SORT AGGREGATE
  INDEX FULL SCAN (MIN/MAX)				IDX_HISTORYALARM$QUERYID

由于索引本身已经排序,因此在计算最大最小值时只需要很小的代价。

索引跳跃扫描

当查询条件中带有符合索引中的列,但是不包含前导列时,就可能导致索引跳跃扫描。数据库将一个复合索引拆分为多个逻辑子索引,符合索引前导列的不同值决定逻辑子索引的数量,即前导列的不同值越少,索引跳跃式扫描的性能就越好。

select value from t3 where value = 'test'

	DESCRIPTION							OBJECT NAME
-----------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS
 INDEX SKIP SCAN						IDX_T3_COMBINE

索引快速全扫描

当索引本身包含查询中指定的所有列时,Oracle执行索引快速全扫描。索引快速全扫描和索引全扫描的区别在于:索引全扫描使用单块读操作,而索引快速全扫描使用多块读。这种扫描不能用于避免排序,因为数据块是通过无序的多块读取来读取的。

select queryid from historyalarm

	DESCRIPTION							OBJECT NAME
-----------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS
 INDEX FAST FULL SCAN					IDX_HISTORYALARM$QUERYID
时间: 2024-10-07 06:06:56

Oracle性能分析6:数据访问方式之索引扫描的相关文章

Oracle 表的访问方式(2)-----索引扫描

索引扫描(Index scan) 我们先通过index查找到数据对应的rowid值(对于非唯一索引可能返回多个rowid值),然后根据rowid直接从表中得到具体的数据,这种查找方式称为索引扫描或索引查找(index lookup).一个rowid唯一的表示一行数据,该行对应的数据块是通过一次i/o得到的,在此情况下该次i/o只会读取一个数据库块.在索引中,除了存储每个索引的值外,索引还存储具有此值的行对应的ROWID值.索引扫描可以由2步组成: (1) 扫描索引得到对应的rowid值. (2)

Oracle性能分析5:数据访问方式之索引结构和扫描方式介绍

上篇文章讲述了全扫描,这篇文章将介绍索引的结构和扫描方式,在后面将开始讲述每一种扫描方式. 当Oracle通过索引检索具体的一列或多列的列值时,就会执行索引扫描.首先我们来看看索引节点包含的数据. 索引节点包含的数据 索引可以被创建在表的单列或者多列上,索引中包含了这些列的值.rowid和一些其它信息,我们关心的只有列值和rowid.由于索引带有列值,应此如果你的SQL语句只涉及到索引的列,那么Oracle就只从索引本身检索列值,而不需要访问表.如果查询涉及到索引列以外的列,Oracle就需要使

Oracle性能分析4:数据访问方法之全扫描

SQL语句执行时,Oracle的优化器会根据统计信息确定表的访问方式,一般来说,有两种基本的数据访问方式:1)全扫描.在全扫描(全表扫描或者快速全索引扫描)中,多个块被读入到一个IO运算中.2)索引扫描.索引扫描首先扫描索引叶子块以取得特定的行id(rowid),然后利用这些行id来访问父表取得实际的行数据,访问通过单块读取来完成.这里主要讲解全扫描方式,后面将介绍索引扫描. 使用全扫描 当对一个表进行全扫描时,会将表中所有数据块(block)取出并进行处理,筛选出符合条件的数据.注意Oracl

Oracle性能分析7:索引的使用

这一节主要讲述索引的使用,首先介绍怎么在查询中避免使用索引,然后介绍优化器怎么判断是否使用索引,并介绍了强制使用索引的方法,最后介绍了Oracle的并行处理方法. 避免使用索引 虽然你创建了索引,但有些查询你可能需要避免使用这些索引,或者你为了做一些测试,希望看看各种情况下查询的情况,也希望能够避免使用一些索引或者索引扫描方式.Oracle提供了方式来达到这些目地,就是在查询中使用hint信息,具体情况如下. 避免使用某个索引 如果索引的选择性很差,那么也许使用其它索引或者使用全表扫描的效率会更

Oracle性能分析12:对象统计信息

对象统计信息描述数据是如何在数据库中存储的,查询优化器使用这些统计信息来做出正确的决定.Oracle中有三种类型的对象统计信息:表统计.列统计和索引统计.而在每种类型中,有细分为:表或索引级别的统计.分区级别统计和子分区级别的统计,后面两种只有在对象被分区和具有子分区的情况下才可用. 统计信息相关视图 表统计信息 表/索引级别的统计 user_tab_statistics user_tables 分区级别的统计 user_tab_statistics user_tab_partitions 子分

Oracle性能分析工具介绍及使用

oracle数据库级别优化分析工具介绍 当我们对数据库优化诊断时,需要收集相应的信息以供参考,从个人的使用经验来说,这种统计数据分为两大类 一类是数据库级别的统计信息二类是os级别的统计信息 下面就分别介绍在不同的级别下,常用什么工具来收集信息帮助优化诊断 首先是oracle数据库级别优化分析工具介绍 目录: 1.statspack2.ASH3.AWR4.ORACLE EXPLAIN PLAN的总结(查询sql的执行计划)   a.autotrace   b.explain的使用 1.stats

Oracle性能分析3:TKPROF介绍

tkprof是Oracle自带的一个命令行工具,主要作用是将原始的跟踪文件转换为格式化的文本文件,最简单的使用方式如下: tkprof ly_ora_128636.trc ly_ora_128636.txt tkprof带有很多参数,在多数情况下,使用这些参数对你的分析将很有帮助. tkprof参数 如果不带任何参数运行tkprof,它将打印出完整的参数列表,并带有简单的描述.下面是对参数的说明: explain 为每个SQL语句提供一个执行计划.该参数需要指定用户.密码,也可以指定数据库连接串

Oracle性能分析1:开启SQL跟踪和获取trace文件

当Oracle查询出现效率问题时,我们往往需要了解问题所在,这样才能针对问题给出解决方案.Oracle提供了SQL执行的trace信息,其中包含了SQL语句的文本信息,一些执行统计,处理过程中的等待,以及解析阶段(如生成执行计划)产生的信息.这些信息有助于你分解sql语句的服务时间和等待时间,并了解所用资源和同步点的详细信息,从而帮助你诊断存在的性能问题. 这篇文章介绍了怎么开启SQL跟踪和获取trace文件,详细信息如下. 开启SQL跟踪 从内部技术细节看,SQL跟踪是基于10046调试事件的

ADO.NET编程之美----数据访问方式(面向连接与面向无连接)

最近,在学习ADO.NET时,其中提到了数据访问方式:面向连接与面向无连接.于是,百度了一下,发现并没有很好的资料,然而,在学校图书馆中发现一本好书(<ASP.NET MVC5 网站开发之美>,当然,我不是做广告的,只因它确实还可以),里面关于二者之间的区别及原理讲得很清楚,下面我们就进入主题.今天心情不错.... 我们都知道ADO.NET提供了对数据库或外部数据源的数据访问接口,它本身实现了面向连接与面向无连接的数据访问方式.面向连接是以数据库连接为基础的,在打开数据库连接后,将数据访问指令