磁盘基本概念

磁盘由大小相同且同轴的圆形盘片组成,磁盘的一侧有磁头支架,磁头支架固定了一组磁头,每个磁头负责存取一个磁盘的内容。磁盘块/簇(虚拟出来的)。 块是操作系统中最小的逻辑存储单位。操作系统与磁盘打交道的最小单位是磁盘块。
通俗的来讲,在Windows下如NTFS等文件系统中叫做簇;在Linux下如Ext4等文件系统中叫做块(block)。每个簇或者块可以包括2、4、8、16、32、64…2的n次方个扇区。

为什么存在磁盘块?

读取方便:由于扇区的数量比较小,数目众多在寻址时比较困难,所以操作系统就将相邻的扇区组合在一起,形成一个块,再对块进行整体的操作。

分离对底层的依赖:操作系统忽略对底层物理存储结构的设计。通过虚拟出来磁盘块的概念,在系统中认为块是最小的单位。

由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,

所以每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存,

预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4KB,InnoDB存储引擎中页的大小为16KB),主存和磁盘以页为单位交换数据。

扇区、块/簇、page的关系

  1. 扇区: 硬盘的最小读写单元
  2. 块/簇: 是操作系统针对硬盘读写的最小单元
  3. page: 是内存与操作系统之间操作的最小单元。

扇区 <= 块/簇 <= page

回顾篇-mysql索引

B-/+Tree索引的性能分析

数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。

复杂度为O(h)=O(logdN),h表示树的高度,d表示页的宽度

B-Tree

 

 

回顾篇-mysql索引

B+Tree

回顾篇-mysql索引

 

 

为什么使用B-Tree(B+Tree)

红黑树等数据结构也可以用来实现索引,但是文件系统及数据库系统普遍采用B-/+Tree作为索引结构,评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度,而红黑树这种结构h(高度)明显要深的多,所以红黑树的I/O渐进复杂度也为O(h),效率明显比B-Tree差很多。由于B+Tree内节点去掉了data域,因此可以拥有更大的出度,拥有更好的性能。

 

MyISAM索引实现

MyISAM引擎使用B+Tree作为索引结构(非聚集),叶节点的data域存放的是数据记录的地址。主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。

 

 

回顾篇-mysql索引

InnoDB索引实现

 

InnoDB引擎使用B+Tree作为索引结构(聚集索引)的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。叶子节点往上部分只起到索引效果,数据都是存放在叶子节点当中的。查数据都要走到叶子节点,所以说稳定性很高。辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。

 

 

 

回顾篇-mysql索引

InnoDB的主键选择

插入数据时候,如果InnoDB页大小达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)。

如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。这种自增主键会形成连续的填充,避免页的碎片化。

回顾篇-mysql索引

 

索引优劣

优势:

  • 提高数据的检索效率,降低数据库的IO成本。
  • 降低CPU的消耗,节能hh。

劣势:

  • 实际上索引也是一张表,表中保存了主键和索引字段,并指向实体类的记录,所以索引列也是要占用空间的。
  • 会降低表更新的速率。每一次表中的insert,update,delete都会使索引维护。

索引分类

单值索引

这也是最常见到的

就是对单个字段(列)建一个索引

每个索引只负责它接管的列数据

一个表中可以包含多个单值索引

唯一索引

前提就是单个字段(列)的值是唯一的,可以包含空值

复合索引

一个索引当中包含了多个字段(列)

对应sql查询,相当于根据XX查找XX。

主键索引

mysql默认创建的

为什么一定要用InnODB?

一、关于count(*)

知识点:MyISAM会直接存储总行数,InnoDB则不会,需要按行扫描。

潜台词是,对于select count(*) from t; 如果数据量大,MyISAM会瞬间返回,而InnoDB则会一行行扫描。

实践:数据量大的表,InnoDB不要轻易select count(*),性能消耗极大。

常见坑:只有查询全表的总行数,MyISAM才会直接返回结果,当加了where条件后,两种存储引擎的处理方式类似。

例如
t_user(uid, uname, age, sex);

  • uid PK

  • age index

select count(*) where age<18 and sex='F';
查询未成年少女个数,两种存储引擎的处理方式类似,都需要进行索引扫描。
启示:不管哪种存储引擎,都要建立好索引。

二、关于全文索引
知识点:MyISAM支持全文索引,InnoDB5.6之前不支持全文索引。

实践:不管哪种存储引擎,在数据量大并发量大的情况下,都不应该使用数据库自带的全文索引,会导致小量请求占用大量数据库资源,而要使用《索引外置》的架构设计方法。

启示:大数据量+高并发量的业务场景,全文索引,MyISAM也不是最优之选。

三、关于事务
知识点:MyISAM不支持事务,InnoDB支持事务。

实践:事务是选择InnoDB非常诱人的原因之一,它提供了commit,rollback,崩溃修复等能力。在系统异常崩溃时,MyISAM有一定几率造成文件损坏,这是非常烦的。但是,事务也非常耗性能,会影响吞吐量,建议只对一致性要求较高的业务使用复杂事务。
画外音:Can't open file 'XXX.MYI'. 碰到过么?

小技巧:MyISAM可以通过lock table表锁,来实现类似于事务的东西,但对数据库性能影响较大,强烈不推荐使用。

 

四、关于外键
知识点:MyISAM不支持外键,InnoDB支持外键。

实践:不管哪种存储引擎,在数据量大并发量大的情况下,都不应该使用外键,而建议由应用程序保证完整性。

 

五、关于行锁与表锁
知识点:MyISAM只支持表锁,InnoDB可以支持行锁。

分析
MyISAM:执行读写SQL语句时,会对表加锁,所以数据量大,并发量高时,性能会急剧下降。
InnoDB:细粒度行锁,在数据量大,并发量高时,性能比较优异。

实践:网上常常说,select+insert的业务用MyISAM,因为MyISAM在文件尾部顺序增加记录速度极快。楼主的建议是,绝大部分业务是混合读写,只要数据量和并发量较大,一律使用InnoDB。

常见坑
InnoDB的行锁是实现在索引上的,而不是锁在物理行记录上。潜台词是,如果访问没有命中索引,也无法使用行锁,将要退化为表锁。
画外音:Oracle的行锁实现机制不同。


启示:InnoDB务必建好索引,否则锁粒度较大,会影响并发。

总结
在大数据量,高并发量的互联网业务场景下,对于MyISAM和InnoDB

  • 有where条件,count(*)两个存储引擎性能差不多

  • 不要使用全文索引,应当使用《索引外置》的设计方案

  • 事务影响性能,强一致性要求才使用事务

  • 不用外键,由应用程序来保证完整性

  • 不命中索引,InnoDB也不能用行锁

结论
在大数据量,高并发量的互联网业务场景下,请使用InnoDB:

  • 行锁,对提高并发帮助很大

  • 事务,对数据一致性帮助很大

这两个点,是InnoDB最吸引人的地方。

 

 

参考:

https://www.cnblogs.com/jinyuanya/p/optimize.html

http://blog.codinglabs.org/articles/theory-of-mysql-index.html

http://www.csyt.cc/news/info/520.html

https://www.cnblogs.com/rouqinglangzi/p/11144960.html

https://blog.csdn.net/qq_17033579/article/details/82950096

https://www.cnblogs.com/roadlandscape/p/12753790.html

btree索引和hash索引的区别

 

 

 

 

 

 

 

 

 

相关文章:

  • 2021-05-12
  • 2021-05-21
  • 2021-06-10
  • 2021-08-10
  • 2021-12-28
  • 2021-06-29
  • 2021-12-30
  • 2021-09-15
猜你喜欢
  • 2021-12-03
  • 2021-07-20
  • 2021-10-26
  • 2021-11-30
  • 2021-09-04
  • 2021-06-11
  • 2022-12-23
相关资源
相似解决方案