Server层:
- 连接器: 身份认证和权限相关(登录 MySQL 的时候)。
- 查询缓存: 执行查询语句的时候,会先查询缓存(MySQL 8.0 版本后移除,因为这个功能不太实用)。
- 分析器: 没有命中缓存的话,SQL 语句就会经过分析器,分析器说白了就是要先看你的 SQL 语句要干嘛,再检查你的 SQL 语句语法是否正确。
词法分析、语法分析 - 优化器: 按照 MySQL 认为最优的方案去执行。
- 执行器: 执行语句,然后从存储引擎返回数据。
过程:
- 查询等过程如下:权限校验—》(查询缓存—》)分析器—》优化器—》权限校验—》执行器—》引擎
- 更新等语句:分析器----》权限校验----》执行器—》引擎—redo log(重做日志) prepare—》binlog(归档日志)—》redo log commit
InnoDB 引擎就是通过 redo log 来支持事务的。
存储引擎:
主要负责数据的存储和读取,采用可以替换的插件式架构,支持 InnoDB、MyISAM、Memory 等多个存储引擎。InnoDB 引擎有自有的日志模块 redolog 模块。现在最常用的存储引擎是 InnoDB。
InnoDB和MyISAM的区别
InnoDB支持事务 ,MyISAM不支持。
支持事务就对数据的完整性更好了,如银行。对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;MyISAM不支持外键;InnoDB支持外键。
对一个包含外键的InnoDB表转为MYISAM会失败。InnoDB 是聚簇索引,使用B+Tree作为索引结构,,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。聚簇索引对于主键的排序查找和范围查找速度非常快。
MyISAM是非聚簇索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
也就是说:InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;而MyISAM的B+树主键索引和辅助索引的叶子节点都是数据文件的地址指针。
既存储了主键值,又存储了行数据,这种结构称为”聚簇索引”
聚集索引两点关键信息:
1)根据主键值创建了 B+ 树结构
2)每个叶子节点包含了整行数据(一行里面的所有东西,,非聚集索引只保留键值和偏移量)
使用聚集索引的查询效率要比非聚集索引的效率要高,但是如果需要频繁去改变聚集索引的值,写入性能并不高,因为需要移动对应数据的物理位置。
InnoDB 存储引擎辅助索引:
叶子节点并不会放整行数据,而存放的是键值和主键 ID。当通过辅助索引来寻找数据时,InnoDB 存储引擎会遍历辅助索引树查找到对应记录的主键,然后通过主键索引来找到对应的行数据。
-
InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快(注意不能加有任何WHERE条件);
那么为什么InnoDB没有了这个变量呢?
因为InnoDB的事务特性,在同一时刻表中的行数对于不同的事务而言是不一样的,因此count统计会计算对于当前事务而言可以统计到的行数,而不是将总行数储存起来方便快速查询。InnoDB会尝试遍历一个尽可能小的索引除非优化器提示使用别的索引。如果二级索引不存在,InnoDB还会尝试去遍历其他聚簇索引。
如果索引并没有完全处于InnoDB维护的缓冲区(Buffer Pool)中,count操作会比较费时。可以建立一个记录总行数的表并让你的程序在INSERT/DELETE时更新对应的数据。和上面提到的问题一样,如果此时存在多个事务的话这种方案也不太好用。如果得到大致的行数值已经足够满足需求可以尝试SHOW TABLE STATUS。 MyISAM支持表级锁(不支持高并发,以读为主);innodb支持行锁(共享锁,排它锁,意向锁),粒度更小,适合处理多重并发的更新请求。
InnoDB的行锁是实现在索引上的,而不是锁在物理行记录上。潜台词是,如果访问没有命中索引,也无法使用行锁,将要退化为表锁。InnoDB表必须有主键(用户没有指定的话会自己找或生产一个主键),而Myisam可以没有。
Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI
Innodb:frm是表定义文件,ibd是数据文件
Myisam:frm是表定义文件,myd是数据文件,myi是索引文件
如何选择存储引擎?
是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;
执行大量select,MyISAM(查询为主)是最好的选择;执行大量的update和insert最好用InnoDB(插入、更新为主),读写都有的。
系统奔溃后,MyISAM恢复起来更困难,能否接受;
MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的,如果你不知道用什么,那就用InnoDB,至少不会差。
InnoDB为什么推荐使用自增ID作为主键?
自增ID可以保证每次插入时B+索引是从右边扩展的,可以避免B+树和频繁合并和分裂(对比使用UUID)。如果使用字符串主键和随机主键,会使得数据随机插入,效率比较差。
innodb引擎的4大特性
插入缓冲(insert buffer),二次写(double write),自适应哈希索引(ahi),预读(read ahead)
InnoDB为什么采用B+树结构实现索引?
- 文件很大,不可能全部存储在内存中,故要存储到磁盘上。
- 索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数(为什么使用B-/+Tree,还跟磁盘存取原理有关。)B+树除了叶子节点其它节点并不存储数据,节点小,磁盘IO次数就少。
- B+树所有的Data域在叶子节点,一般来说都会进行一个优化,就是将所有的叶子节点用指针串起来,这样遍历叶子节点就能获得全部数据。
以 InnoDB 的一个整数字段索引为例,这个 N 差不多是 1200。这棵树高是 4 的时候,就可以存 1200 的 3 次方个值,这已经 17 亿了。考虑到树根的数据块总是在内存中的,一个 10 亿行的表上一个整数字段的索引,查找一个值最多只需要访问 3 次磁盘。其实,树的第二层也有很大概率在内存中,那么访问磁盘的平均次数就更少了。
结论:InnoDB采用B+树结构,是因为B+树能够很好地配合磁盘的读写特性,减少单次查询的磁盘访问次数,降低IO、提升性能。
如何解决非聚集索引的二次查询问题
建立两列以上的索引,即可查询复合索引里的列的数据而不需要进行回表二次查询。
从 innodb 的索引结构分析,为什么索引的 key 长度不能太长?
key 太长会导致一个页当中能够存放的 key 的数目变少,间接导致索引树的页数目变多,索引层次增加,从而影响整体查询变更的效率。