索引扫描的过程

来源:互联网 发布:超市广播录音软件 编辑:程序博客网 时间:2024/06/08 18:02

1、例子:select id from big_table where id=42;(索引在ID上)
因为因为索引的高度是3,那么一致性读就是3,先读了根块,再读枝块,再读叶块,没有回表。(索引=KEY+ROWID,这里KEY就是ID=42)
如果是select * from big_table where id=42; 那么一致性读肯定大于3。
索引在逻辑上是顺序的,物理上是随机的。索引在物理上读是分散的。但是索引在逻辑上读是顺序的。经常可以看到遮掩的等待:db file sequential read 这个就是顺序读,其实这里就是读索引等待。索引它不会要求我们按一种连续的方式读取块1、然后是块2,接着是块3.我们将以一种非常随意的方式读取和重新读取块。这种块I/O 可能非常慢。


2、B*树索引的扫描
唯一性扫描

 INDEX KEY=XXX 就遍历了树的高度,如果是INDEX KEY > XXX AND INDEX KEY < YYYY,那是涉及索引范围遍历。

范围扫描
范围扫描先找到查询的最小值,一直遍历到索引键值的最大值,比如,a >50 and a<100。找50的话,就从根,到枝,再到叶,叶和叶节点之间,都有指针相连,这时候,我们就从50开始,再找兄弟叶节点
如果索引的碎片比较多的话,那么范围扫描非常慢。那么就需要重建索引或者合并索引。

全索引扫描
找到索引第1个叶节点,一直扫描到最后一个叶节点

快速全索引扫描
扫描的索引反馈给用户时没有顺序要求,这样,我们可以物理的对索引块进行顺序访问,这样,我们可以实现索引块的多块读。
前面的index full scan,我们简称ifs
后面这个index fast full scan,我们简称iffs

 

3、补充几个概念:随机访问/顺序访问,离散读/顺序读
 当oracle进程需要访问数据文件里的数据块时,oracle会有两种类型的I/O操作方式:
随机访问:每次读取一个数据块(通过等待事件“db file sequential read”顺序读体现出来)。
顺序访问:每次读取多个数据块(通过等待事件“db file scattered read”随机读体现出来)。
第一种方式则是访问索引里的数据块,而第二种方式的I/O操作属于全表扫描。这里顺带有一个问题,为何随机访问会对应到db file sequential read等待事件,而顺序访问则会对应到db file scattered read等待事件呢?这似乎反过来了,随机访问才应该是分散(scattered)的,而顺序访问才应该是顺序(sequential)的。其实,等待事件主要根据实际获取物理I/O块的方式来命名的,而不是根据其在I/O子系统的逻辑方式来命名的。下面对于如何获取索引数据块的方式中会对此进行说明。
我们看到前面对B树索引的体系结构的描述,可以知道其为一个树状的立体结构。其对应到数据文件里的排列当然还是一个平面的形式,也就是像下面这样。因此,当oracle需要访问某个索引块的时候,势必会在这个结构上跳跃的移动。
/根/分支/分支/叶子/…/叶子/分支/叶子/叶子/…/叶子/分支/叶子/叶子/…/叶子/分支/.....
当oracle需要获得一个索引块时,首先从根节点开始,根据所要查找的键值,从而知道其所在的下一层的分支节点,然后访问下一层的分支节点,再次同样根据键值访问再下一层的分支节点,如此这般,最终访问到最底层的叶子节点。可以看出,其获得物理I/O块时,是一个接着一个,按照顺序,串行进行的。在获得最终物理块的过程中,我们不能同时读取多个块,因为我们在没有获得当前块的时候是不知道接下来应该访问哪个块的。因此,在索引上访问数据块时,会对应到db file sequential read等待事件,其根源在于我们是按照顺序从一个索引块跳到另一个索引块,从而找到最终的索引块的。
那么对于全表扫描来说,则不存在访问下一个块之前需要先访问上一个块的情况。全表扫描时,oracle知道要访问所有的数据块,因此唯一的问题就是尽可能高效的访问这些数据块。因此,这时oracle可以采用同步的方式,分几批,同时获取多个数据块。这几批的数据块在物理上可能是分散在表里的,因此其对应到db file scattered read等待事件。

 

原创粉丝点击