一 前言:
• ROWID:包含键值的行的行ID,(查找块的最快方法,类似于门牌号)
• 因为所有行属于同一个段,所以要使用受限的ROWID 指向表行
索引是数据库为了提高查询效率提供的一种冗余结构,保守计算数据库50%以上的调优可以通过调整索引来进行优化;
二 索引在结构上的类别可划分如下:B树索引、位图索引、散列索引、反转索引等
三 索引的介绍:
1、B树索引(BTREE
B数索引是我们日常工作最最常用的索引,大家平时在工作中说的"索引"默认都是B数索引;
索引其实很简单,也很容易理解,用一本书的目录来形容最为贴切了,B树索引的结构跟图书馆的目录也很像
B树索引的结构:
索引的顶层为根,它包括指向索引中下一层次的条目。下一层次为分支块,它又指向位于索引中下一层索引中下一层次的块,最底层的是叶节点,它包含指向表行的索引条目。叶块是双向关联的,这边与按键值升序或降序扫描索引;
索引叶条目的格式
一个索引条目包含以下组件:
• 条目头:存储列数和锁定信息
• 键列长度/值对:用于定义键中的列大小,后面跟随列值(此类长度/值对的数目就是索引中的最大列数)。
索引叶条目的特性
在非分区表的B 树索引中:
• 当多个行具有相同的键值时,如果不压缩索引,键值会出现重复
• 当某行包含的所有键列为NULL 时,该行没有对应的索引条目。因此,当WHERE 子句指定了NULL 时,将始终执行全表扫描
对索引执行DML 操作的效果
对表执行DML 操作时,Oracle 服务器会维护所有索引。下面说明对索引执行DML 命令产生的效果:
• 执行插入操作导致在相应块中插入索引条目。
• 删除一行只导致对索引条目进行逻辑删除。已删除行所占用的空间不可供后面新的叶条目使用。
• 更新键列导致对索引进行逻辑删除和插入。PCTFREE 设置对索引没有影响,但创建时除外。即使索引块的空间少于PCTFREE 指定的空间,也可以向索引块添加新条目。
该图更能体现索引的结构
2、位图索引
位图索引(bitmap index)是从Oracle7.3 版本开始引入的。目前Oracle 企业版和个人版都支持位图索引,但标准版不支持。
位图索引在平时的OLTP系统中比较少见,但是在OLAP系统中就会经常见到,号称数据仓库调优的三个利器之一;
位图索引(通过在以下特定情况下,位图索引比B 树索引更有优势:
• 表具有数百万行且键列的基数较低时(也就是列的不同值极少时)。例如,对于护照记录表中的性别和婚姻状况列,位图索引可能比B 树索引更可取。
• 经常使用包含OR 运算符的多个WHERE 条件组合进行查询时
• 键列上的活动为只读活动或少量更新活动时(OLAP系统的特点)
位图索引的结构
位图索引也可以按B 树形式进行组织,但是,叶节点会存储每个键值的位图,而不是行ID 列表。位图中每一位与一个可能的行ID 对应,如果设置了该位,则表示具有对应行ID 的行包含键值。
如图所示,位图索引的叶节点包含:
• 条目头,其中包含列数和锁定信息
• 由每个键列的长度/值对组成的键值(在幻灯片的示例中,关键字只由一列组成;第一个条目的键值为Blue)
• 开始ROWID,在本示例中它指定块号10、行号0 和文件号3
• 结束ROWID,在本示例中它指定块号12、行号8 和文件号3
• 由位字符串组成的位图段(如果对应行包含键值,则会设置位;如果对应行不包含键值,则不会设置位。Oracle 服务器使用已获专利的压缩技术存储位图段。)开始ROWID 是位图中的位图段指向的第一行的行ID,也就是说,位图的第一位对应于该行ID,位图的第二位对应于块中的下一行。结束ROWID 是一个指针,它指向由位图段覆盖的表中的最后一行。位图索引使用受限的行ID。
使用位图索引
B 树用于定位叶节点,这些节点包含指定键值的位图段。开始ROWID 和位图段用于定位包含键值的行。
对表中的键列进行更改后,也必须修改位图。这会导致相关的位图段被锁定。由于锁是在整个位图段上获得的,因此,在第一个事务处理结束之前,其它事务处理不能更新位图覆盖的行。
理论文章会告诉你值重复率高的字段不适合建索引。不要说性别字段只有两个值,网友亲测,一个字段使用拼音首字母做值,共有26种可能,加上索引后,百万加的数据量,使用索引的速度比不使用索引要慢!
一个表可能会涉及两个数据结构(文件),一个是表本身,存放表中的数据,另一个是索引。索引是什么?它就是把一个或几个字段(组合索引)按规律排列起来,再附上该字段所在行数据的物理地址(位于表中)。比如我们有个字段是年龄,如果要选取某个年龄段的所有行,那么一般情况下可能需要进行一次全表扫描。但如果以这个年龄段建个索引,那么索引中会按年龄值建一个排列,这样在索引中就能迅速定位,不需要进行全表扫描。
为什么性别不适合建索引呢?因为你访问索引需要付出额外的IO开销,你从索引中拿到的只是地址,要想真正访问到数据还是要对表进行一次IO。假如你要从表的100万行数据中取几个数据,那么利用索引迅速定位,访问索引的这IO开销就非常值了。但如果你是从100万行数据中取50万行数据,就比如性别字段,那你相对需要访问50万次索引,再访问50万次表,加起来的开销并不会比直接对表进行一次完整扫描小。同时,虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据还要更新索引。建立索引会占用磁盘空间。一般情 况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。
当然凡事不是绝对,如果把性别字段设为表的聚集索引,那么就肯定能加快大约一半该字段的查询速度了。聚集索引指的是表本身中数据按哪个字段的值来进行排序。因此,聚集索引只能有一个,而且使用聚集索引不会付出额外IO开销。当然你得能舍得把聚集索引这么宝贵资源用到性别字段上。
(键值重复高的字段也可以建立位图索引)
B树索引是一对一的,一个索引条目指向一行,而位图索引中索引条目非常少,每个条目指向多行,它适合一些特殊的环境,单纯的比较他们的环境是没有意义的,因为应用的环境不一样。