数据库索引浅析

1. 数据库存储引擎

MyISAM存储引擎

(1) MyISAM存储引擎不支持事务、表锁设计,支持全文索引,在MySQL5.5.8版本之 前MyISAM存储引擎是默认的存储引擎(除windows版本外)。
(2) MyISAM存储引擎的另 一个与众不同的地方是它的缓冲池只缓冲索引文件,而不缓冲数据文件,数据文件的缓冲交由操作系统本身来完成(大部分数据库使用LRU算法缓存数据)。
(3) MySQL 存储引擎表由MYD和MYI组成,MYD用来存放数据文件,MYI用来存放索引文件。
(4) MyISAM默认支持的表大小为4GB,如果需要支持大于4GB的 MyISAM表时,则需要制定MAX_ROWS和AVG_ROW_LENGTH属性。从MySQL5.0版本开始, MySQL默认支持256T的表单数据。
(5) MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。

这里写图片描述
MyISAM中索引检索的算法为:首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data 域的值,然后以data域的值为地址,读取相应数据记录。 MyISAM的索引方式也叫做“非聚集索引”的。

InnoDB存储引擎

(1) InnoDB存储引擎支持事务,其设计目标主要面向在线事务处理的应用,其特点是行锁设计、支持外键,并支持类似Oracle的非锁定读,即默认读取操作不会产生锁。
(2) 从MySQL数据库5.5.8版本开始,InnoDB存储引擎是默认的存储引擎。 > >(3) InnoDB 存储引擎将数据存放在一个逻辑的表空间中,这个空间就像黑盒一样由 Inno DB 存储引擎自身进行管理。
(4) InnoDB存储引擎还提供了插入缓冲、二次写、自适应哈希索引、预读等高性能和高可用的功能。
(5) 对于表中数据的存储,InnoDB存储引擎采用了聚集的方式,因此每张表的存储都是按主键的顺序存放的,如果没 有显式地在表定义时指定主键,InnoDB存储引擎会为每一行生成一个6字节的 ROWID,并以此作为主键。
(6) InnoDB支持B+树索引、全文索引、哈希索引。但InnoDB使用B+Tree作为索引结 构时,具体实现方式却与MyISAM截然不同。

这里写图片描述
区别
(1)InnoDB的数据文件本身就是索引文件。MyISAM索引文件和数据文件 是分离的,索引文件仅保存数据记录的地址。而InnoDB索引,表数据文件本身 就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据 记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索 引。

(2)是InnoDB的辅助索引data域存储相应记录主键的值而不是地址, 所有 辅助索引都引用主键作为data域。

2. 底层采用B+树的原因

  1. 一般使用磁盘I/O次数评价索引结构的优劣。根据B-Tree的定义可知,一次 检索最多需要访问h个节点。数据库系统的设计者巧妙利用了磁盘预读原理,将 一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入.
  2. 为了达到这个目的,在实际实现B-T re e还需要使用如下技巧:每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里, 加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。B-Tree 中一次检索最多需要h-1次I/O(根节点常驻内存),渐进复杂度 为O(h)=O(logdN) 。
  3. 一般实际应用中,出度d是非常大的数字,通常超过10 0,因此h 非常小(通常 不超过3 )。综上所述,用B-Tree作为索引结构效率是非常高的。
  4. 而红黑树这种 结构,h明显要深的多。由于逻辑上很近的节点(父子)物理上可能很远,无法 利用局部性,所以红黑树的I/O渐进复杂度也为O(h),效率明显比B-Tree差很多。
  5. 上文还说过,B+Tree更适合外存索引,原因和内节点出度d 有关。从上面分析 可以看到,d 越大索引的性能越好,而出度的上限取决于节点内ke y和da ta 的大小: dmax =f l oor ( pa gesize/(keysize+da tas iz e+p oi nts iz e)) fl oor 表示向下取整。由于 B+Tr ee 内节点去掉了data域,因此可以拥有更大的出度,拥有更好的性能。
3. 索引创建原则

为表设置索引是要付出代价的
1、 增加了数据库的存储空间
2、 在插入和修改数据时要花费较多的时间(因为索引也要随之变动)
创建索引可以大大提高系统的性能:
1、通过创建唯一性所以,可以保证数据库表中每一行的数据的唯一性
2、可以大大加快数据的检索速度
3、可以加速表与表之间的连接,特别是在实现数据的参考完整性方面特别有意义
4、在使用分组和排序子句进行检索时,同样可以显著减少查询中分组和排序的时间
5、通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能
那是否是在一张表中每一个列都创建一个索引更好呢?
不是,因为增加索引也有许多不利的方面:
1、创建索引和维护索引需要耗费时间,这种时间随着数据量的增加而增加 2、索引需要占用物理空间,除了数据表占数据空间之外,每一个索引还要占用一定的物理空间,如果要建立聚簇索引,那么需要的空间就更大
3、当对表中的数据进行增删改时,索引也要动态维护,降低了数据的维护速度
索引建立在数据库表中的某些列上面。
在创建索引的时候,一般应该:
1、经常需要搜索的列上,可以加快搜索的速度
3、在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度 4、在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,在指定的范围是连续的
5、在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间
6、在经常需要使用在where子句中的列上创建索引,加快条件的判读速度
不应该创建索引的列
1、对于那些在查询中很少使用或者参考的列不应该创建索引。因为既然这些列很少使用,因此有索引或者无索引,并不能提高查询速度,相反增加了索 引,反而降低了系统的维护速度和增大了空间需求
2、对于那些只有很少数据值的列也不应该建立索引。因为这些列的取值很少,例如人事表的性别,在查询的结果中,结果集的数据行占了表中数据行的 很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
3、对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
4、当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

猜你喜欢

转载自blog.csdn.net/qq_37954088/article/details/81808121