【数据库系列(三)】数据库索引

索引的作用  

  在数据库系统的使用过程当中,数据的查询是使用最频繁的一种数据操作。最直接的是顺序查找,但是可以想象数据量大了之后 O(n) 时间复杂度的顺序查找是不能满足需求的。另外二分查找要求数据有序,二叉树查找要求是树结构。我么会发现查找算法都是依赖于特定的数据结构。但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织),所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引
  索引是对数据库表 中一个或多个列的值进行排序的结构。与在表中搜索所有的行相比,索引用指针指向存储在表中指定列的数据值,然后根据指定的次序排列这些指针,有助于更快地获取信息。通常情 况下,只有当经常查询索引列中的数据时 ,才需要在表上创建索引。因为其占用磁盘空间,影响数据的更新速度。但是在多数情况下 ,索引所带来的数据检索速度优势大大超过它的不足之处。
  数据库的索引大多是基于B+树实现的,那么什么是B+树, 关于树的问题,可以参考笔者数据结构的帖子,不多做赘述。
  

B+树

特性介绍

   B+树是应文件系统所需而产生的一种B-树的变形树。其结构如下图:
这里写图片描述
  通常在B+树上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点。因此可以对B+树进行两种查找运算:一种是从最小关键字起顺序查找,另一种是从根节点开始,进行随机查找。
  B+的特性:
1.所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好
是有序的;
2.不可能在非叶子结点命中;
3.非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储
(关键字)数据的数据层;
4.更适合文件索引系统;

在数据库索引中的组织方式

① 叶结点的组织方式 。
  1. 查找键是数据文件的主键 ,且索引是稠密的。
  2. 数据文件按主键排序,且是稀疏索引 , 在叶结点中为数据文件的每一个块设有一个键、指针对 ;
  3. 数据文件不按主键排序 ,叶结点中为数据文件里出现的每个属性K设有一个键 、 指针对 , 其中指针指向排序键值为 K的 记录中的第一个。

② 非叶结点 的组织方式。B+树 中的非叶结点形成 了叶结点上的一个多级稀疏索引。

索引分类

稠密索引与稀疏索引

  稠密索引: 块中只存放记录的键以及指向记录本身的指针,稠密索引文件中的索引块保持键的顺序与文件中的排序顺序一致。
这里写图片描述

  第一个索引块存放指向前四个记录的指针,第二个索引块存放指向接下来的四个记录的指针,依此类推。
  给定一个键值K,我们先在索引块中查找K。当找到K后,我们按照K所对应的指针到数据文件中找到相应的记录。

  稀疏索引: 稀疏索引只为数据文件的每个存储块设一个键-指针对。它比稠密索引节省了更多的存储空间,但查找给定值的记录需更多的时间。
  这里写图片描述
  在已有稀疏索引的情况下,要找出查找键值为K的记录,我们得在索引中查找到键值小于或等于K的最大键值。由于索引文件已按键排序,我们可以使用二分查找法来定位这个索引项,然后根据它的指针找到相应的数据块。现在我们必须搜索这个数据块以找到键值为K的记录。
  
  

聚集索引与非聚集索引

  聚集索引表示表中存储的数据按照索引的顺序存储,检索效率比非聚集索引高,但对数据更新影响较大。该索引中键值的逻辑顺序决定了表中相应行的物理顺序。
  以查字典为例:
  比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是“an”,而按照拼音排序汉字的字典是以英文字母“a”开头并以“z”结尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个字,那么就说明您的字典中没有这个字;同样的,如果查“张”字,那您也会将您的字典翻到最后部分,因为“张”的拼音是“zhang”。也就是说,字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。
  
  非聚集索引表示数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置,非聚集索引检索效率比聚集索引低,但对数据更新影响较小。
  以查字典为例:
  根据“偏旁部首”去查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“张”字,我们可以看到在查部首之后的检字表中“张”的页码是672页,检字表中“张”的上面是“驰”字,但页码却是63页,“张”的下面是“弩”字,页面是390页。很显然,这些字并不是真正的分别位于“张”字的上下方,现在您看到的连续的“驰、张、弩”三字实际上就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的结果,然后再翻到您所需要的页码。我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为“非聚集索引”。
  

顺序索引与散列索引

  有两种基本的索引结构,也就是索引文件的保存方式,一个是顺序索引,就是根据值的顺序排序的(这个文件里面的值,也就是为其建索引的字段值,是顺序的放在索引文件里面),另外一个是散列索引,就是将值平均分配到若干散列桶中,通过散列函数定位的。
  顺序索引: 单级索引(不怎么用)和多级索引(通常是B+树)
  散列索引:通过散列函数来定义的一种索引

MySQL上的存储方式

  在 MySQL 中,主要有四种类型的索引,分别为: B-Tree 索引, Hash 索引, Fulltext 索引和 R-Tree 索引。其中 B-Tree 索引是 MySQL 数据库中使用最为频繁的索引类型

1. MyISAM索引实现:
1)主索引
  MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM主键索引的原理图:
  这里写图片描述

  这里设表一共有三列,假设我们以Col1为主键,上图是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址。
  2)辅助索引
  在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。
  这里写图片描述
  同样也是一颗B+Tree,data域保存数据记录的地址。因此,MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。

  MyISAM的索引方式也叫做“非聚集”的,之所以这么称呼是为了与InnoDB的聚集索引区分。
  
2. InnoDB索引实现:  
  InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同.
  1)主键索引:
  MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。
  这里写图片描述
  上图是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。
  2) InnoDB的辅助索引
InnoDB的所有辅助索引都引用主键作为data域。例如,下图为定义在Col3上的一个辅助索引:
这里写图片描述
  InnoDB 表是基于聚簇索引建立的。因此InnoDB 的索引能提供一种非常快速的主键查找性能。不过,它的辅助索引(Secondary Index, 也就是非主键索引)也会包含主键列,所以,如果主键定义的比较大,其他索引也将很大。如果想在表上定义 、很多索引,则争取尽量把主键定义得小一些。InnoDB 不会压缩索引。
文字符的ASCII码作为比较准则。聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。
不同存储引擎的索引实现方式对于正确使用和优化索引都非常有帮助,例如知道了InnoDB的索引实现后,就很容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。再例如,用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

InnoDB索引和MyISAM索引的区别:
一是主索引的区别,InnoDB的数据文件本身就是索引文件。而MyISAM的索引和数据是分开的。
二是辅助索引的区别:InnoDB的辅助索引data域存储相应记录主键的值而不是地址。而MyISAM的辅助索引和主索引没有多大区别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值