oracle索引

索引的结构

1基础概念

为了掌握索引的原理,首先需要掌握一些基本概念。

(1)       索引和表在磁盘上是存放在一起还是分开的?

(2)       一个表上的所有索引是在一起存放的还是独立的?

(3)       索引和表在磁盘上的存放方式有什么不同?

(4)       索引和表之前是如何关联的?

(5)       索引的作用是什么?

1.1索引和表是独立的对象

Oracle中有很多种对象,包括表、索引、存储过程、触发器、序列、视图等。这些对象都有自己的定义语句,保存在数据字典(oracle系统创建的表)中。对于表和索引,数据字典中出了需要保存对象的定义,还需要保存对象的数据。

索引和表是对立的对象,它们分别拥有自己的存储空间,并不是放在一起的,所以它们可以存放在不同的表空间中。一个表上如果有多个索引,那每个索引也是独立的对象,拥有自己的存储空间。两个索引之前是没有关系的。

1.2索引和表在磁盘上存放方式

         表和索引的数据都存放在磁盘的数据块中,每个数据块一般固定为8k。数据块是数据读写的最小单位,即使只需要读取一条数据,也会把整块的数据读到内存中,写数据也一样。

         表中的数据是无序的存放在数据库块中,两个数据块完全没有关系,同一个数据块中的数据也没有关系。数据在表中的顺序也不一定是录入的顺序,后录入的数据也可能在前面。

         如果想从表中查询某条数据,在没有索引的情况下就只能全表扫描所有的数据块,即全表扫描。

         于表的无序存放不同,索引是有序存放的。在存放索引的数据块上,数据都是有序的,并且数据块之前使用指针进行关联。

1.3索引和表之间是如何关联的

索引中保存:索引的键值(索引列的值);数据在表中的地址(rowid)。

若通过Oracle索引查找ID=10的数据,那么就到ID索引中先找到目标数据的地址(rowid),然后根据数据地址到表中查看数据。

1.4索引的作用

         使用索引是为了快速找到目标数据,因为全表扫描慢。

 

数据块是数据读写的最小单位。

在表中数据是无序堆放的,而索引中的数据块是有序的,使用指针关联。

索引中只保存索引键的值和数据地址。

使用索引为了快速查找目标数据

 

2 B+索引结构

         Oracle有很多种类型的索引,最常用的是B+树索引。它是一种树形结构,每个节点是个数据块,每个父节点可以有多个子节点。

 

2.1 根节点、分支节点和叶子节点

         索引的数据块会组成一个树形结构,索引块之间以指针的形式链接。索引树有根节点块、分支节点块、叶子节点块。

         每个索引只有一个根节点块,但可以有多个分支节点快和叶子节点块。索引的层高是从根节点到叶子节点的高度。每个索引只能包含一层叶子节点块,索引的所有叶子界定啊在同一层。

2.2 索引块的内容

         每个索引块包含条数据,该数据只保存键值和一个指针地址,指向下一级的索引块或数据块。对于根节点和分支节点,它需要根据这个指针找到对应的子节点。对于叶子节点,它需要根据这个指针找到对应的数据地址。

         在叶子节点中,每个数据块还会保存相邻的叶子节点的地址。在每一层索引节点和每个索引块中,索引的键值都是有序的,默认升序。

 

索引树有根节点块、分支几点块和叶子节点块。索引的所有叶子节点在同一层。

每个父节点中如果有N条数据,那么就有N个指针指向子节点。

在叶子节点中,每个数据块还会白村相邻的叶子节点的地址。

在每一层索引节点和每个索引块中,索引的键值都是有序的,默认升序。

 

3 表和索引的存储分析

3.1 表的存储结构分析

一个表占用多少数据块由多方面的因素决定:

(1)       数据行数,数据越多占用的空间越大。

(2)       每条数据的长度,如果表的列很少,并且每个列的长度都很短,那么表占用的数据块就少,反之则占用得多

(3)       如果很多数据被delete了,数据占用的数据块并不会被释放,这就是高水位,当有新数据insert时会优先占用空闲的数据块。

3.2 索引的存储结构分析

(1) 同一个表的索引存的数据并不一样多:索引不包含空的键值

(2) 索引的层高不会太高

         一个索引块大概能存400个左右数据,三层即400*400*400=6400万,四层则上百亿的数据,所以一般索引的层高不会太高

(3) 索引占的数据块比较少

         若表的列很少,但是有多个索引,这种情况也有可能索引占的总空间不比表的空间小

(4)       每个键值占的叶子的块数

每个键值占的叶子块数是个平均值,如果索引列是唯一的,那么每个键值最多占一个叶子块,如果索引列的重复值很多,那么就可能占很多歌叶子块。如果一个键值的重复度很高,使用这个索引查询的效率可能就很低。索引的高度决定了从根节点到叶子节点要查询几个索引块。而键值的重复度决定了要查询多少个叶子块。

(5)       每个键值指向的表的块数

每个键值指向的表块数也是个平均值。比如一个索引键有20条数据,它一般只需要一个索引叶子块,但是在表中,这40条数据可能在1个块中也可能在20个块中。

 

索引中不包含空的键值,一般不能根据索引查询空值

索引每层能容纳的数据随层高增大呈指数级增加,所以索引的层高不会很大

不建议在长度很大的列或者很多字段的组合索引上创建索引,这样索引树会很高,查询效率很低

索引占的数据块一般比表少得多

索引键值重复度很高,那么查询效率可能很低

当查询的键值对应很多个数据块时,查询效率比较低

 

 

性能调优基础

1.IO,CPU和network的关系

         IO是指把数据从磁盘读到内存的过程;CPU主要是指处理内存中数据的过程,有时包括等待IO时间;network指数据在网络中传输的过程。三种性能瓶颈是此消彼长的关系。

         实际应用中,网络的开销是比较小的,因为大部分的运算是在数据库完成的,所以需要重点关注IO和CPU。降低IO就是减少读取磁盘数据块,降低CPU就是减少读取内存块,所以读取的数据块越少,消耗的资源也就越少,性能也越好。

2.逻辑读与物理读

         逻辑读是指要读的数据块已经在缓存中不需要发生实际的IO,这时主要消耗CPU;而物理读是指缓存中没有要读的数据块,需要发生实际的IO,这时消耗的主要是IO。如一些数据经常被读取,那么就很可能在内存中命中,不需要物理读。

         逻辑读比物理读要快的多,这也就是第二次执行会比第一次执行快的原因了

3.多块读、随机读和顺序读

         IO是最消耗资源的,那么哪些方法可以减少IO消耗呢

(1)              合理的业务需求:如果每次查询都要把大表统计一遍,那么会有大量的IO,即使逻辑读也是影响性能的。

(2)              多块读:如果操作系统的缓存比较大,而且要读取得数据块是相邻的,那么就可以使用多块读,一次IO读取多个数据块,这样可以减少IO的消耗。对表做全表扫描是可以使用多块读的,因为表每次申请的空间(extent)都是连续的,而普通的索引扫描就不适合,索引块之间是指针连续的,但是同一个索引块中的数据在表中也不一定是连续的。

(3)              顺序读和随机读:顺序读比随机读效率高得多。

 

性能调优的根本方法就是减少读取的数据块

全表扫描可以支持多块读,而索引扫描一般只能支持单块读

顺序IO比随机IO效率高,索引扫描一般是随机IO

 

posted @ 2018-07-11 22:53  八千步  Views(558)  Comments(0Edit  收藏  举报