(0-0)
表的访问
01
全表扫描
全表扫描是指Oracle在访问目标表的数据时,会从该表所占用的第一个分区(EXTENT)的第一个块(BLOCK)开始扫描,一直扫描到该表的高水位线(HWM,High Water Mark),这个范围内所有的数据块Oracle都必须读到。
Oracle在做全表扫描操作时会使用多块读,这在目标表数据量不大时执行效率是非常高的,但全表扫描最大的问题就在于走全表扫描的目标SQL的执行时间会不稳定、不可控,这个执行时间一定会随着目标表数据量的递增而递增。
在Oracle中,如果不停的往目标表里插入数据,当分配给该表的现有表空间不足时,高水位线就会向上移动,但当用DELETE语句删除该表数据时,高水位线不会向下移动。
高水位线的副作用是,即使使用DELETE语句删光了目标表数据,高水位线还在原来的位置,这以为这全表扫描时Oracle还是需要扫描该表高水位线下的所有数据块,所以此时对该表的全表扫描操作所消耗的时间与之前比并不是明显的改观
02
ROWID扫描
ROWID扫描是指Oracle在访问目标表数据时,直接通过数据所在的ROWID去定位并访问这些数据。ROWID表示的是Oracle中数据行记录所在的物理存储地址,且同数据块中的行记录一一对应。
ROWID扫描的两层含义:一种是根据用户在SQL语句中输入的ROWID的值直接去访问对应的数据行记录;另外一种是先去访问相关的索引,然后根据访问索引后得到的ROWID在回表去访问对应的数据行记录。

拓展
利用DBMS_ROWID包中的相关方法翻译对应数据行的实际物理存储位置
dbms_rowid.rowid_relative_fno(rowid)--数据行对应的文件号
dbms_rowid.rowid_block_number(rowid)--数据行对应的第几个数据块
dbms_rowid.rowid_row_number(rowid)--数据行对应的第几个记录(数据块中的记录号从0开始)

(0-0)
索引的访问

Oracle数据库中B树索引的结构
注:此处提到的索引都是B树索引,Oracle数据库里其他类型的索引这里暂不考虑;
Oracle中的B树索引包含两种类型的数据块,一种是索引分支块,另外一种是索引叶子块。
索引分支块包含指向相应索引分支块/叶子块的指针和索引键值列(这里的指针是指相关分支块/叶子块的块地址RDBA。每个索引分支块都会有两种类型的指针,一种是lmc,另一种是索引分支块的索引行记录所记录的指针。lmc是Left Most Child的缩写,每个索引分支块都有一个lmc,这个lmc指向的分支块/叶子块中的所有索引键值列中的最大值一定小于该lmc索引分支块的所有索引键值列中的最小值;而索引分支块的索引行记录所记录的指针所指向的分支块/叶子块的所有所有键值列中的最小值一定大于或等于该行记录的索引键值列的值)。索引键值列不一定是完整的被索引键值,它可能是被索引键值的前缀,只要Oracle能通过这些前缀区分相应的索引分支块/叶子块就行,这样既节省索引分支块的存储空间,又可以快速定位其下层的索引分支块/叶子块。索引分支块最上层的那个块就是所谓的索引根节点。
索引叶子块包含被索引键值和用于定位该索引键值所在的行记录在表中实际物理存储位置的ROWID。唯一性B树索引,ROWID存储在索引行的行头,Oracle则不需要额外存储该ROWID的长度。非唯一性B树索引,ROWID被当做额外的列与被索引键值列一起存储,Oracle既要存储ROWID又要存储其长度,这意味着同等条件下,唯一B树索引比非唯一B树索引节省索引叶子块的存储空间。对于非唯一B树索引而言,B树索引的有序性体现在Oracle会按照被索引键值和相应的ROWID来联合排序。Oracle中的索引叶子块是左右互联的,即相当于有一个双向指针链表把这些索引叶子块连接在一起。
OracleB树索引的优势
1、所有的索引叶子块都在同一层,即他们距离索引根节点的深度相同。这也意味着访问索引叶子块的任何一个索引键值所花费的时间是一样的
2、Oracle会保证所有的B树索引都是自平衡的,即不可能出现不同的索引叶子块不处于同一层的现象。
3、通过B树索引访问表里行记录的效率并不会随着相关表的数据量递增而降低,即通过索引访问数据的时间是可控的、基本稳定的,这是走索引和全表扫描的最大区别。
03
索引唯一性扫描
索引唯一性扫描(INDEX UNIQUE SCAN)是针对唯一性索引(UNIQUE INDEX)的扫描,仅仅适用于where条件里等值查询的目标SQL
04
索引范围扫描
索引范围扫描(INDEX RANGE SCAN)
适用于所有类型的B树索引。
当扫描的对象是唯一索引时,此时目标SQL的where条件一定是范围扫描(BETWEEN、>、<等)
当扫描的对象是非唯一索引时,对目标SQL的where条件没有限制(可以是等值查询,也可以是范围查询)
同等条件下,当目标索引的索引行的数量大于1时,索引范围扫描所消耗的逻辑读至少会比相应的索引唯一性扫描的逻辑读多1

拓展
清空数据字典缓存和Buffer Cache
Alter system flush share_pool;//请勿随意在生产执行
Alter system flush buffer_cache;//请勿随意在生产执行

05
索引全扫描
索引全扫描(INDEX FULL SCAN)
适用于所有类型的B树索引(包括唯一索引和非唯一索引)
索引全扫描指扫描索引所有叶子块的索引行。需要注意的是,索引全扫描不一定需要扫描索引的所有分支块。默认情况下,Oracle在做索引全扫描时指需要通过访问必要的分支块定位到位于该索引最左侧的叶子块的第一行索引行,就可以利用该索引叶子块之间的双向指针链表,从左至右依次顺序扫描该索引所有的索引行。
索引全扫描能够达到排序的效果,又同时避免了对该索引的索引键值列的真正排序
06
索引快速全扫描
索引快速全扫描(INDEX FAST FULL SCAN)
索引快速全扫描同索引全扫描极为类似,它也适用于所有类型的B树索引。
索引快速全扫描同索引全扫描的区别
(1)索引快速全扫描适用于CBO。
(2)索引快速全扫描可以使用多块读,也可以并行执行。
(3)索引快速全扫描的执行结果不一定是有序的。这是因为索引快速全扫描时Oracle是根据索引行在磁盘上的物理存储顺序来扫描,而不是根据索引行的逻辑顺序来扫描的,所以不一定有序(对于单个索引叶子块而言,其物理存储顺序和逻辑存储顺序一致;但对于物理存储位置相邻的索引叶子块而言,块与块之间索引行的物理存储顺序不一定在逻辑顺序上有序)。
07
索引跳跃式扫描
索引跳跃式扫描(INDEX SKIP SCAN)
适用于所有类型的符合B树索引
索引跳跃式扫描使在where条件中没有对目标索引的前导列指定查询条件同时又对该索引的非前导列指定了查询条件的目标SQL可以使用上该索引。
Oracle中的索引跳跃式扫描仅仅适用于那些目标索引前导列的distinct值数量较少、后续非前导列的可选择性又非常好的情形,因为索引跳跃式扫描的执行效率一定会随着目标索引前导列的distinct值数量的递增而递减。
END
扫描二维码
获取更多精彩
如初幻自由
