面试连环炮之Mysql
面试连环炮系列专栏,暂不想换工作的同学可补充知识盲点查缺补漏,准备换工作的同学可针对性突击训练,不打无准备之战。面试战场所向披靡,成为offer收割机,找到心仪的工作。
楼主努力更新,争取每日多更。有想关注的方向可留言,楼主针对性更新。已更新的内容也会不断更新完善增加更多的"炮弹",祝大家面试时可以吊打面试官。
目录
1、MySQL体系结构
2、mysql常用存储引擎?
3、sql执行过程
4、两阶段提交
5、Mysql事务四大特性?
6、ACID四大特性实现原理?
7、Mysql锁分类?
8、Mysql有哪些日志?
9、常见索引模型?
10、什么是回表,什么是覆盖索引,索引下推?
11、MySQL索引类别及注意事项
12、Mysql执行计划
14、Mysql高可用
15、生产Mysql服务器配置
1、MySQL体系结构
Mysql由应用层、MySQL服务层、存储引擎层构成。
应用层:连接处理、用户鉴权、安全管理
服务层:MySQL Management Server & utilities(系统管理)、SQL Interface(SQL 接口)、SQL Parser(SQL 解析器)、Optimizer (查询优化器)、Caches & buffers(缓存)
存储引擎层:存储引擎、物理文件
2、mysql常用存储引擎?
mysql常用存储引擎InnoDB 、MyISAM 、Memory等。
3、sql执行过程
Buffer Pool
作首先就是针对这个内存中的Buffer Pool里的数据执行的,同时配合了后续的redo log、刷磁盘等机制和操作。
所以Buffer Pool就是数据库的一个内存组件,里面缓存了磁盘上的真实数据,然后我们的Java系统对数据库执行的增删改操
作,其实主要就是对这个内存数据结构中的缓存数据执行的。
redo log(重做日志)
Mysql如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到 对应的那条记录,然后再更新,整个过程 IO 成本、查找成本都很高。
当Mysql有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。InnoDB 的 redo log 是固定大小的,如果redo log 满了,这时候不能再执行新的更新,得停下来先擦 掉一些记录,把 checkpoint 推进一下写入磁盘。有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失, 这个能力称为crash-safe。
binlog(归档日志)
redo log 是 InnoDB 引擎特有的日志,而 Server 层也有自己的日志,称为 binlog(归档日志)。
1、redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可 以使用。
2.、redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志, 记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
3、redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
redo log和undo log都属于InnoDB的事务日志。
4、两阶段提交
“两阶段提交”是为了让两份日志之间的逻辑一致。
数据恢复过程
比如某天下午两点发现中午十二点有一次误删表,需要找回数 据,那你可以这么做: 首先,找到最近的一次全量备份,如果你运气好,可能就是昨天晚上的一个备份,从这个备 份恢复到临时库;
然后,从备份的时间点开始,将备份的 binlog 依次取出来,重放到中午误删表之前的那个时 刻。
这样你的临时库就跟误删之前的线上库一样了,然后你可以把表数据从临时库取出来,按需要恢 复到线上库去。
参数配置
innodb_flush_log_at_trx_commit 这个参数设置成 1 的 时候,表示每次事务的 redo log 都直接持久化到磁盘。这个参数建议你设置成 1,这样可以 保证 MySQL 异常重启之后数据不丢失。
sync_binlog 这个参数设置成 1 的时候,表示每次事务的 binlog 都持久化到磁盘。这个参数也建议你设置成 1,这样可以保证 MySQL 异常重启之后 binlog 不丢失。
5、Mysql事务四大特性?
事务的四个特性ACID:原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
- 原子性:语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的;实现主要基于undo log
- 持久性:保证事务提交后不会因为宕机等原因导致数据丢失;实现主要基于redo log
- 隔离性:保证事务执行尽可能不受其他事务影响;InnoDB默认的隔离级别是RR,RR的实现主要基于锁机制(包含next-key lock)、MVCC(包括数据的隐藏列、基于undo log的版本链、ReadView)
- 一致性:事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的保障
6、ACID四大特性实现原理?
原子性
原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做;如果事务中一个sql语句执行失败,则已执行的语句也必须回滚,数据库退回到事务前的状态。
undo log是实现原子性的关键,是当事务回滚时能够撤销所有已经成功执行的sql语句。InnoDB实现回滚,靠的是undo log:当事务对数据库进行修改时,InnoDB会生成对应的undo log;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。
undo log属于逻辑日志,它记录的是sql执行相关的信息。当发生回滚时,InnoDB会根据undo log的内容做与之前相反的工作:对于每个insert,回滚时会执行delete;对于每个delete,回滚时会执行insert;对于每个update,回滚时会执行一个相反的update,把数据改回去。
隔离性
隔离性是指,事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。严格的隔离性,对应了事务隔离级别中的Serializable (可串行化),但实际应用中出于性能方面的考虑很少会使用可串行化。
隔离性追求的是并发情形下事务之间互不干扰。简单起见,我们主要考虑最简单的读操作和写操作(加锁读等特殊读操作会特殊说明),那么隔离性的探讨,主要可以分为两个方面:
- (一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性
- (一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性
什么是锁机制?
首先来看两个事务的写操作之间的相互影响。隔离性要求同一时刻只能有一个事务对数据进行写操作,InnoDB通过锁机制来保证这一点。
锁机制的基本原理可以概括为:事务在修改数据之前,需要先获得相应的锁;获得锁之后,事务便可以修改数据;该事务操作期间,这部分数据是锁定的,其他事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。
行锁与表锁
按照粒度,锁可以分为表锁、行锁以及其他位于二者之间的锁。表锁在操作数据时会锁定整张表,并发性能较差;行锁则只锁定需要操作的数据,并发性能好。但是由于加锁本身需要消耗资源(获得锁、检查锁、释放锁等都需要消耗资源),因此在锁定数据较多情况下使用表锁可以节省大量资源。MySQL中不同的存储引擎支持的锁是不一样的,例如MyIsam只支持表锁,而InnoDB同时支持表锁和行锁,且出于性能考虑,绝大多数情况下使用的都是行锁。
如何查看锁信息
有多种方法可以查看InnoDB中锁的情况,例如:
select * from information_schema.innodb_locks; #锁的概况
show engine innodb status; #InnoDB整体状态,其中包括锁的情况
#在事务A中执行:start transaction;update account SET balance = 1000 where id = 1;#在事务B中执行:start transaction;update account SET balance = 2000 where id = 1;
show engine innodb status查看锁相关的部分:
通过上述命令可以查看事务占用锁的情况;其中lock_type为RECORD,代表锁为行锁(记录锁);lock_mode为X,代表排它锁(写锁)。
除了排它锁(写锁)之外,MySQL中还有共享锁(读锁)的概念。
脏读、不可重复读和幻读?
脏读:当前事务(A)中可以读到其他事务(B)未提交的数据(脏数据),这种现象是脏读。举例如下(以账户余额表为例):
(2)不可重复读:在事务A中先后两次读取同一个数据,两次读取的结果不一样,这种现象称为不可重复读。脏读与不可重复读的区别在于:前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据。举例如下:
(3)幻读:在事务A中按照某个条件先后两次查询数据库,两次查询结果的条数不同,这种现象称为幻读。不可重复读与幻读的区别可以通俗的理解为:前者是数据变了,后者是数据的行数变了。举例如下:
事务隔离级别?
SQL标准中定义了四种隔离级别,并规定了每种隔离级别下上述几个问题是否存在。一般来说,隔离级别越低,系统开销越低,可支持的并发越高,但隔离性也越差。隔离级别与读问题的关系如下:
在实际应用中,读未提交在并发时会导致很多问题,而性能相对于其他隔离级别提高却很有限,因此使用较少。可串行化强制事务串行,并发效率很低,只有当对数据一致性要求极高且可以接受没有并发时使用,因此使用也较少。因此在大多数数据库系统中,默认的隔离级别是读已提交(如Oracle)或可重复读(后文简称RR)。
InnoDB默认的隔离级别是RR,在SQL标准中,RR是无法避免幻读问题的,但是InnoDB实现的RR避免了幻读问题。
什么是mvcc?
RR解决脏读、不可重复读、幻读等问题,使用的是MVCC:MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议。下面的例子很好的体现了MVCC的特点:在同一时刻,不同的事务读取到的数据可能是不同的(即多版本)——在T5时刻,事务A和事务C可以读取到不同版本的数据。
MVCC最大的优点是读不加锁,因此读写不冲突,并发性能好。InnoDB实现MVCC,多个版本的数据可以共存,主要基于以下技术及数据结构:
1)隐藏列:InnoDB中每行数据都有隐藏列,隐藏列中包含了本行数据的事务id、指向undo log的指针等。
2)基于undo log的版本链:前面说到每行数据的隐藏列中包含了指向undo log的指针,而每条undo log也会指向更早版本的undo log,从而形成一条版本链。
3)ReadView:通过隐藏列和版本链,MySQL可以将数据恢复到指定版本;但是具体要恢复到哪个版本,则需要根据ReadView来确定。所谓ReadView,是指事务(记做事务A)在某一时刻给整个事务系统(trx_sys)打快照,之后再进行读操作时,会将读取到的数据中的事务id与trx_sys快照比较,从而判断数据对该ReadView是否可见,即对事务A是否可见。
trx_sys中的主要内容,以及判断可见性的方法如下:
- low_limit_id:表示生成ReadView时系统中应该分配给下一个事务的id。如果数据的事务id大于等于low_limit_id,则对该ReadView不可见。
- up_limit_id:表示生成ReadView时当前系统中活跃的读写事务中最小的事务id。如果数据的事务id小于up_limit_id,则对该ReadView可见。
- rw_trx_ids:表示生成ReadView时当前系统中活跃的读写事务的事务id列表。如果数据的事务id在low_limit_id和up_limit_id之间,则需要判断事务id是否在rw_trx_ids中:如果在,说明生成ReadView时事务仍在活跃中,因此数据对ReadView不可见;如果不在,说明生成ReadView时事务已经提交了,因此数据对ReadView可见。
是RR隔离级别下“非加锁读”实现隔离性的方式。下面是一些简单的扩展。
(1)读已提交(RC)隔离级别下的非加锁读
RC与RR一样,都使用了MVCC,其主要区别在于:
RR是在事务开始后第一次执行select前创建ReadView,直到事务提交都不会再创建。根据前面的介绍,RR可以避免脏读、不可重复读和幻读。
RC每次执行select前都会重新建立一个新的ReadView,因此如果事务A第一次select之后,事务B对数据进行了修改并提交,那么事务A第二次select时会重新建立新的ReadView,因此事务B的修改对事务A是可见的。因此RC隔离级别可以避免脏读,但是无法避免不可重复读和幻读。
(2)加锁读与next-key lock
按照是否加锁,MySQL的读可以分为两种:
一种是非加锁读,也称作快照读、一致性读,使用普通的select语句,这种情况下使用MVCC避免了脏读、不可重复读、幻读,保证了隔离性。
加锁读在查询时会对查询的数据加锁(共享锁或排它锁)。由于锁的特性,当某事务对数据进行加锁读后,其他事务无法对数据进行写操作,因此可以避免脏读和不可重复读。而避免幻读,则需要通过next-key lock。next-key lock是行锁的一种,实现相当于record lock(记录锁) + gap lock(间隙锁);其特点是不仅会锁住记录本身(record lock的功能),还会锁定一个范围(gap lock的功能)。因此,加锁读同样可以避免脏读、不可重复读和幻读,保证隔离性。
InnoDB实现的RR,,通过锁机制(包含next-key lock)、MVCC(包括数据的隐藏列、基于undo log的版本链、ReadView)等,实现了一定程度的隔离性,可以满足大多数场景的需要。
不过需要说明的是,RR虽然避免了幻读问题,但是毕竟不是Serializable,不能保证完全的隔离,
持久性
持久性是指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
实现原理:redo log
InnoDB作为MySQL的存储引擎,数据是存放在磁盘中的,但如果每次读写数据都需要磁盘IO,效率会很低。为此,InnoDB提供了缓存(Buffer Pool),Buffer Pool中包含了磁盘中部分数据页的映射,作为访问数据库的缓冲:当从数据库读取数据时,会首先从Buffer Pool中读取,如果Buffer Pool中没有,则从磁盘读取后放入Buffer Pool;当向数据库写入数据时,会首先写入Buffer Pool,Buffer Pool中修改的数据会定期刷新到磁盘中(这一过程称为刷脏)。
Buffer Pool的使用大大提高了读写数据的效率,但是也带了新的问题:如果MySQL宕机,而此时Buffer Pool中修改的数据还没有刷新到磁盘,就会导致数据的丢失,事务的持久性无法保证。
于是,redo log被引入来解决这个问题:当数据修改时,除了修改Buffer Pool中的数据,还会在redo log记录这次操作;当事务提交时,会调用fsync接口对redo log进行刷盘。如果MySQL宕机,重启时可以读取redo log中的数据,对数据库进行恢复。redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改先写入日志,再更新到Buffer Pool,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。
既然redo log也需要在事务提交时将日志写入磁盘,为什么它比直接将Buffer Pool中修改的数据写入磁盘(即刷脏)要快呢?主要有以下两方面的原因:
(1)刷脏是随机IO,因为每次修改的数据位置随机,但写redo log是追加操作,属于顺序IO。
(2)刷脏是以数据页(Page)为单位的,MySQL默认页大小是16KB,一个Page上一个小修改都要整页写入;而redo log中只包含真正需要写入的部分,无效IO大大减少。
一致性
一致性是指事务执行结束后,数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。数据库的完整性约束包括但不限于:实体完整性(如行的主键存在且唯一)、列完整性(如字段的类型、大小、长度要符合要求)、外键约束、用户自定义完整性(如转账前后,两个账户余额的和应该不变)。
一致性是事务追求的最终目标:前面提到的原子性、持久性和隔离性,都是为了保证数据库状态的一致性。此外,除了数据库层面的保障,一致性的实现也需要应用层面进行保障。
实现一致性的措施包括:
- 保证原子性、持久性和隔离性,如果这些特性无法保证,事务的一致性也无法保证
- 数据库本身提供保障,例如不允许向整形列插入字符串值、字符串长度不能超过列的限制等
- 应用层面进行保障,例如如果转账操作只扣除转账者的余额,而没有增加接收者的余额,无论数据库实现的多么完美,也无法保证状态的一致
7、Mysql锁分类?
数据库锁设计的初衷是处理并发问题。作为多用户共享的资 源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁就是用来实现这些访 问规则的重要数据结构。
MySQL 里面的锁大致可以分成全局锁、表级锁和行锁三类。
全局锁
对整个数据库实例加锁。当你需要让整个库处于只读状态的时候,可以使用这个 命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包 括建表、修改表结构等)和更新类事务的提交语句。全局锁的典型使用场景是,做全库逻辑备份。
如果你在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆;
如果你在从库上备份,那么备份期间从库不能执行主库同步过来的 binlog,会导致主从延 迟。
全局锁主要用在逻辑备份过程中。对于全部是 InnoDB 引擎的库,mysqldump建议使用–single transaction 参数,对应用会更友好。
表级锁
面表级别的锁有两种:一种是表锁,一种是元数据锁(meta data lock,MDL)。
表锁一般是在数据库引擎不支持行锁的时候才会被用到的。
MDL 会直到事务提交才释放,在做表结构变更的时候,一定要小心不要导致锁住线上查询和更新。
行级锁
的行锁是在引擎层由各个引擎自己实现的。但并不是所有的引擎都支持行锁,比如 MyISAM 引擎就不支持行锁。不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表, 同一张表上任何时刻只能有一个更新在执行,这就会影响到业务并发度。InnoDB 是支持行锁 的,这也是 MyISAM 被 InnoDB 替代的重要原因之一。
InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。
如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。
死锁和死锁检测
当出现死锁以后,有两种策略:
一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数innodb_lock_wait_timeout 来设置。
另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑。
在 InnoDB 中,innodb_lock_wait_timeout 的默认值是 50s,意味着如果采用第一个策略,当出现死锁以后,第一个被锁住的线程要过 50s 才会超时退出,然后其他线程才有可能继续执行。对于在线服务来说,这个等待时间往往是无法接受的。
正常情况下我们还是要采用第二种策略,即:主动死锁检测,而且innodb_deadlock_detect 的默认值本身就是 on。主动死锁检测在发生死锁的时候,是能够快
速发现并进行处理的,但是它也是有额外负担的。
8、Mysql有哪些日志?
MySQL的日志有很多种,如二进制日志、错误日志、查询日志、慢查询日志等,此外InnoDB存储引擎还提供了两种事务日志:redo log(重做日志)和undo log(回滚日志)。其中redo log用于保证事务持久性;undo log则是事务原子性和隔离性实现的基础。MySQL中还存在binlog(二进制日志)也可以记录写操作并用于数据的恢复。
redo log与binlog
(1)作用不同:redo log是用于crash recovery的,保证MySQL宕机也不会影响持久性;binlog是用于point-in-time recovery的,保证服务器可以基于时间点恢复数据,此外binlog还用于主从复制。
(2)层次不同:redo log是InnoDB存储引擎实现的,而binlog是MySQL的服务器层(可以参考文章前面对MySQL逻辑架构的介绍)实现的,同时支持InnoDB和其他存储引擎。
(3)内容不同:redo log是物理日志,内容基于磁盘的Page;binlog的内容是二进制的,根据binlog_format参数的不同,可能基于sql语句、基于数据本身或者二者的混合。
(4)写入时机不同:binlog在事务提交时写入;redo log的写入时机相对多元:
前面曾提到:当事务提交时会调用fsync对redo log进行刷盘;这是默认情况下的策略,修改innodb_flush_log_at_trx_commit参数可以改变该策略,但事务的持久性将无法保证。
除了事务提交时,还有其他刷盘时机:如master thread每秒刷盘一次redo log等,这样的好处是不一定要等到commit时刷盘,commit速度大大加快。
9、常见索引模型?
1、聚簇索引的顺序就是数据的物理存储顺序,而对非聚簇索引的解释是:索引顺序与数据物理排列顺序无关。正是因为如此,所以一个表最多只能有一个聚簇索引。在SQL Server中,索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。
2、索引是一种特殊的数据结构。微软的SQL Server提供了两种索引:聚集索引(Clustered Index,也称聚类索引、簇集索引、聚簇索引)和非聚集索引(Nonclustered Index,也称非聚类索引、非簇集索引)。创建的索引,如复合索引、前缀索引、唯一索引,都是属于非聚簇索引,在有的书籍中,又将其称为辅助索引(secondary index)。在后文中,我们称其为非聚簇索引,其数据结构为B+树。
3、聚簇索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的就是整张表的行记录数据,也将聚集索引的叶子节点称为数据页。Innodb通过主键聚集数据,如果没有定义主键,innodb会选择非空的唯一索引代替。如果没有这样的索引,innodb会隐式的定义一个主键来作为聚簇索引。
索引的常见模型
索引的出现是为了提高查询效率,但是实现索引的方式却有很多种,所以这里也就引入了索引模 型的概念。比较常见得索引模型有哈希表、有序数组和搜索树等。
哈希表
哈希表这种结构适用于只有等值查询的场景,比如redis以及一些NoSql引擎。
有序数组
而有序数组在等值查询和范围查询场景中的性能就都非常优秀,有序数组索引只适用于静态存储引擎。
二叉搜索树
二叉搜索树是经典数据结构。为了维持 O(log(N)) 的查询复杂度,就需要保持这棵树是平衡二叉树。为了做这个保证,更新的时间复杂度也是 O(log(N))。
树可以有二叉,也可以有多叉。N 叉树由于在读写上的性能优点,以及适配磁盘的访问模式,已经被广泛应用在数据库引擎中 了。
InnoDB 的索引模型
在 InnoDB 中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织 表。又因为前面我们提到的,InnoDB 使用了 B+ 树索引模型,所以数据都是存储在 B+ 树中 的。
主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)。 非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引。
即主键查询方式,则只需要搜索 ID 这棵 B+ 树;
普通索引查询方式,则需要先搜索 k 索引树, 得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表。回到主键索引树搜索的过程称为回表。基于非主键索引的查询需要多扫描一棵索引树。
索引维护
B+ 树为了维护索引有序性,在插入新值的时候需要做必要的维护。
如果插入数据所在的数据页已经满了,根据 B+ 树的算法,这时候需要申请一个新 的数据页,然后挪动部分数据过去。这个过程称为页分裂。在这种情况下,性能自然会受影响。除了性能外,页分裂操作还影响数据页的利用率。
有分裂就有合并,当相邻两个页由于删除了数据,利用率很低之后,会将数据页做合并。合并的过程,可以认为是分裂过程的逆过程。
最左前缀原则
B+ 树这种索引结构,可以利用索引的“最左前缀”,来定位记录。不只是索引的全部定义,只要满足最左前缀,就可以利用索引来加速检索。这个最左 前缀可以是联合索引的最左 N 个字段,也可以是字符串索引的最左 M 个字符。如果通过调整顺序, 可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。
10、什么是回表,什么是覆盖索引,索引下推?
回表的路径需要扫描两遍索引树,第一遍先通过普通索引定位到主键值id=5,然后第二遍再通过聚集索引定位到具体行记录。这就是所谓的回表查询,即先定位主键值,再根据主键值定位行记录,性能相对于只扫描一遍聚集索引树的性能要低一些。
索引遍历过程中对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能 优化手段。索引覆盖是一种避免回表查询的优化策略。具体的做法就是将要查询的数据作为索引列建立普通索引(可以是单列索引,也可以一个索引语句定义所有要查询的列,即联合索引),这样的话就可以直接返回索引中的的数据,不需要再通过聚集索引去定位行记录,避免了回表的情况发生。
索引覆盖
索引覆盖是一种避免回表查询的优化策略。具体的做法就是将要查询的数据作为索引列建立普通索引(可以是单列索引,也可以一个索引语句定义所有要查询的列,即联合索引),这样的话就可以直接返回索引中的的数据,不需要再通过聚集索引去定位行记录,避免了回表的情况发生。
11、MySQL索引类别及注意事项
MySQL目前主要有以下几种索引类型:
1.普通索引
2.唯一索引
3.主键索引
4.组合索引
5.全文索引
使用索引时,有以下一些技巧和注意事项:
1.索引不会包含有null值的列
只要列中包含有null值都将不会被包含在索引中,复合索引中只要有一列含有null值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为null。
2.使用短索引
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个char(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
3.索引列排序
查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
4.like语句操作
一般情况下不推荐使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。
5.不要在列上进行运算
这将导致索引失效而进行全表扫描。
6.不使用not in和<>操作
sql的优化主要是围绕着在查询语句的时候尽量使用索引避免全表扫描。
12、Mysql执行计划
每条sql执行mysql都会经过成本和规则的优化,然后优化过后,就会得到一个执行计划。
一般成本是两块,首先是那些数据如果在磁盘里,
你要不要从磁盘里把数据读出来?这个从磁盘读数据到内存就是IO成本,而且MySQL里都是一页一页读的,读一页的成本的
约定为1.0。
还有一个成本,那就是说你拿到数据之后,是不是要对数据做一些运算?比如验证他是否符合搜索条件了,或者是搞一些排序分组之类的事,这些都是耗费CPU资源的,属于CPU成本,一般约定读取和检测一条数据是否符合条件的成本是0.2.
下面分别对EXPLAIN命令结果的每一列进行说明:
1. ID列
- ID列中的如果数据为一组数字,表示执行SELECT语句的顺序;如果为NULL,则说明这一行数据是由另外两个SQL语句进行 UNION操作后产生的结果集
- ID值相同时,说明SQL执行顺序是按照显示的从上至下执行的
- ID值不同时,ID值越大代表优先级越高,则越先被执行
2. SELECT_TYPE列
值 | 含义 |
---|---|
SIMPLE | 不包含子查询或是UNION操作的查询 |
PRIMARY | 查询中如果包含任何子查询,那么最外层的查询则被标记为PRIMARY |
SUBQUERY | SELECT 列表中的子查询 |
DEPENDENT SUBQUERY | 依赖外部结果的子查询 |
UNION | Union操作的第二个或是之后的查询的值为union |
DEPENDENT UNION | 当UNION作为子查询时,第二或是第二个后的查询的select_type值 |
UNION RESULT | UNION产生的结果集 |
DERIVED | 出现在FROM子句中的子查询 |
3. TABLE列
包含以下几种结果:
输出去数据行所在表的名称,如果表取了别名,则显示的是别名
<union M,N>: 由ID为M,N查询union产生的结果集
<derived N>/<subquery N> :由ID为N的查询产生的结果
4. PARTITIONS列:
查询匹配的记录来自哪一个分区
对于分区表,显示查询的分区ID
对于非分区表,显示为NULL
5. TYPE列
按性能从高至低排列如下:
值 | 含义 |
---|---|
system | 这是const联接类型的一个特例,当查询的表只有一行时使用 |
const | 表中有且只有一个匹配的行时使用,如对主键或是唯一索引的查询,这是效率最高的联接方式 |
eq_ref | 唯一索引或主键索引查询,对应每个索引键,表中只有一条记录与之匹配 |
ref | 非唯一索引查找,返回匹配某个单独值的所有行 |
ref_or_null | 类似于ref类型的查询,但是附加了对NULL值列的查询 |
index_merge | 该联接类型表示使用了索引合并优化方法 |
range | 索引范围扫描,常见于between、>、<这样的查询条件 |
index | FULL index Scan 全索引扫描,同ALL的区别是,遍历的是索引树 |
ALL | FULL TABLE Scan 全表扫描,这是效率最差的联接方式 |
6. Extra列
包含MySQL如何执行查询的附加信息
值 | 含义 |
---|---|
Distinct | 优化distinct操作,在找到第一个匹配的元素后即停止查找 |
Not exists | 使用not exists来优化查询 |
Using filesort | 使用额外操作进行排序,通常会出现在order by或group by查询中 |
Using index | 使用了覆盖索引进行查询 |
Using temporary | MySQL需要使用临时表来处理查询,常见于排序,子查询,和分组查询 |
Using where | 需要在MySQL服务器层使用WHERE条件来过滤数据 |
select tables optimized away | 直接通过索引来获得数据,不用访问表,这种情况通常效率是最高的 |
7. POSSIBLE_KEYS列
指出MySQL能使用哪些索引来优化查询
查询列所涉及到的列上的索引都会被列出,但不一定会被使用
8. KEY列
查询优化器优化查询实际所使用的索引
如果表中没有可用的索引,则显示为NULL
如果查询使用了覆盖索引,则该索引仅出现在Key列中
9. KEY_LEN列
显示MySQL索引所使用的字节数,在联合索引中如果有3列,假如3列字段总长度为100个字节,Key_len显示的可能会小于100字节,比如30字节,这就说明在查询过程中没有使用到联合索引的所有列,只是利用到了前面的一列或2列
- 表示索引字段的最大可能长度
- Key_len的长度由字段定义计算而来,并非数据的实际长度
10. Ref列
表示当前表在利用Key列记录中的索引进行查询时所用到的列或常量
11. rows列
- 表示MySQL通过索引的统计信息,估算出来的所需读取的行数(关联查询时,显示的是每次嵌套查询时所需要的行数)
- Rows值的大小是个统计抽样结果,并不十分准确
12. Filtered列
- 表示返回结果的行数占需读取行数的百分比
- Filtered列的值越大越好(值越大,表明实际读取的行数与所需要返回的行数越接近)
- Filtered列的值依赖统计信息,所以同样也不是十分准确,只是一个参考值
Using Index | 表示索引覆盖,不会回表查询 |
---|---|
Using Where | 表示进行了回表查询 |
Using Index Condition | 表示进行了ICP优化 |
Using Flesort | 表示MySQL需额外排序操作, 不能通过索引顺序达到排序效果 |
14、Mysql高可用
一般生产环境里用于进行数据库高可用架构管理的工具是MHA,分为两种节点,一个是Manager节点,一个是Node节点,
Manager节点一般是单独部署一台机器的,Node节点一般是部署在每台MySQL机器上的,因为Node节点得通过解析各个MySQL的日志来进行一些操作。
接着进行主从复制的搭建,全部按照之前的步骤走就行了,可以选择异步复制,当然也可以是半同步复制的。
主从策略:异步复制、半同步复制。
15、生产Mysql服务器配置
数据库部署的时候常选用的机器配置最低在8核16G以上,正常在16核32G。
一般8核16G的机器部署的MySQL数据库,每秒抗个一两千并发请求是没问题的,对于16核32G的机器部署的MySQL数据库而言,每秒抗个两三千,甚至三四千的并发请求也都是可以的。
不管你多牛,一定要提前准备,千万不要裸面。另外面试准备也尽量不要死记硬背,要结合自己项目的情况有自己的见解。不管是面试中级、高级还是架构岗位都最好准备一些新技术架构的思考,比如云原生、Service Mesh、中台、DevOps等等。
关注公众号小猿架构,发送 yys 免费获取 《云原生技术与架构实践》。
面试连环炮之Mysql相关推荐
- 分库分表的4个面试连环炮问题!不会就惨了!
作者:Yang Libin https://github.com/doocs/advanced-java 面试中我们经常会碰到的关于分库分表的几个面试连环炮!今天就给大家一一介绍!希望对大家面试的时候 ...
- 面试题:消息队列面试连环炮
目录: 你使用过消息中间件吗? 你们为什么使用消息中间件? 消息队列有什么好处? 什么场景下使用的?用来干了个什么的事情? 系统中引入消息队列之后会不会有什么坏处? 你们使用哪一个消息中间件?为什么选 ...
- 【求锤得锤的故事】Redis锁从面试连环炮聊到神仙打架。
来自:why技术 又到了一周一次的分享时间啦,老规矩,还是先荒腔走板的聊聊生活. 有上面的图是读大学的时候,一次自行车骑行途中队友抓拍的我的照片.拍照的地方,名字叫做牛背山,一个名字很 low,实际很 ...
- 去BAT面试完的Mysql面试题总结(55道)
转载自 去BAT面试完的Mysql面试题总结(55道,带完整答案) 55道互联网大公司的经典面试题,全部答对月薪5W+没问题. 1.一张表里面有ID自增主键,当insert了17条记录之后,删除了第 ...
- 面试被问mysql扩展性设计相关的点,你知道该如何回答吗
面试被问mysql扩展性设计相关的点,你知道该如何回答吗 什么是扩展性 横向扩展(Scale Out) 和纵向扩展(Scale Up)区别 横向扩展 纵向扩展 事务相关性最小化原则 解决方案 敲黑板. ...
- 分布式系统面试连环炮
分布式系统面试连环炮 有一些同学,之前呢主要是做传统行业,或者外包项目,一直是在那种小的公司,技术一直都搞的比较简单.他们有共同的一个问题,就是都没怎么搞过分布式系统,现在互联网公司,一般都是做分布式 ...
- 面试连环炮:从HashSet开始,一路怼到CPU
之前在金三银四,我面试了20家互联网公司这篇文章中提到我在今年四月份面试了大大小小近20家互联网公司,然后总结出来一套由浅入深的Java基础面试题连环炮.本文主要给出这些面试题的答案. 由浅入深了解这 ...
- 【求锤得锤的故事】Redis锁从面试连环炮聊到神仙打架
背景铺垫 面试的时候,不管你的简历写没写 Redis,它基本上是一个绕不过的话题. 为了引出本文要讨论的关于 Redlock 的神仙打架的问题,我们就得先通过一个面试连环炮: Redis 做分布式锁的 ...
- 面试连环炮之分布式锁
面试连环炮系列专栏,暂不想换工作的同学可补充知识盲点查缺补漏,准备换工作的同学可针对性突击训练,不打无准备之战.面试战场所向披靡,成为offer收割机,找到心仪的工作. 楼主努力更新,争取每日多更. ...
最新文章
- 浅谈likely与unlikely
- IDEA 2021.3 正式发布:支持远程开发、故障排查、Java和Spring等多项优化改进
- java xml添加节点_Java对XML节点的修改、添加、删除 –By Xstream框架
- mysql空表_MySQL中两种快速创建空表的方式
- 『数学』--数论--组合数+卢卡斯定理+扩展卢卡斯定理
- 余承东:华为P40或是鸿蒙系统首款手机,新机明年3月发布
- PHP exit()与die()的区别
- ConstraintLayout使用汇总
- 删除服务列表中的Tomcat服务?(或删除服务列表中的任意服务)
- 【问题集合】3dsMax贴图模糊(2016)
- IMPDP ORA-39125 / LPX-00241
- 006-深度学习与NLP简单应用
- Iaas、Paas、Saas都是什么意思?
- 拉格朗日乘子法、对偶、KTT
- 算法中的数学基础知识
- 数据可视化(三)基于 Graphviz 实现程序化绘图
- java ora 01002,ORA-01002 提取违反顺序
- python高清壁纸_爬虫 抓取王者荣耀所有英雄皮肤高清壁纸(完美版本)
- Support Vector Machine学习笔记
- mysql join 自联结_MySQL JOIN | 联结