@x-power
2022-12-26T06:04:42.000000Z
字数 2705
阅读 244
面试
MySQL
可以分为server
层和存储引擎层两部分
Server
层包括连接器、查询缓存、分析器、优化器、执行器等,其涵盖MySQL
的大多数核心服务功能,以及所有的内置函数,所有跨存储引擎的功能都在这一层实现,比如存储过程,触发器,视图等。InnoDB
、MyISAM
、Memory
等多个存储引擎。现在最常用的存储引擎是InnoDB
.TCP
握手之后,连接器就要开始认证身份。mysql -h $ip -P $port -u user -p $Password
key
为查询语句,而value
为结果。select * from t1 join t2 using ID where t1.c=10 and t2.d=20;
既可以先到表
t1
中找到c=10
,然后再根据ID
的关联到t2
中找d=20
的记录。也可以相反操作。这两种执行方法的逻辑结果是一样的,但是执行的效率有所不同,而优化器就是选择效率高的方法。
select * from T where ID=10
如果ID字段没有索引的话,那么执行器的执行流程是这样的:
1. 调用Innodb
引擎接口读取这个表的第一行,判断ID值是否为10
,如果不是则跳过,如果是则将改行存在结果集中;
2. 调用引擎接口读取下一行,重复相同的判断逻辑,知道这个表的最后一行。
3. 执行器将上述便利过程中所有满足条件的行组成的记录集合作为结果集返回给客户端。
索引的出现就是为了提高数据查询的效率,就想书的目录一样。对于数据库的表而言,索引其实就是它的目录。
如果一张表中没有主键索引,
mysql
就会默认创建一个长度为6字节的rowid
主键。
索引主要有:唯一索引、主键(聚集)索引、非聚集(普通)索引。
select * from T where ID=500
,即主键查询方式,则只需要搜索ID
这一棵B+
树。select * from T where k=5
,即普通索引,则需要先搜索k
索引树,得到的ID
值为500,然后再搜索ID一次,这个操作被称为回表操作。change buffer
。唯一索引,由于需要验证数据的唯一性,因此每次更新操作都需要读磁盘将数据加载进内存,设计IO操作。因此需要尽量减少唯一索引作为查询条件使用,以避免增加IO操作。在不影响数据一致性的前提下,
InnoDB
会将这些更新操作缓存在change buffer
中,这样就不需要从磁盘中读入这个数据也了。在下次查询需要访问这个数据也的时候,将数据也读入内存,然后执行change buffer
中与这个页有关的操作。通过该种方式就可以保证数据逻辑完整性。
change buffer
中的操作应用到原数据页,得到最新结果的过程称为merge
。
1. 访问这个数据页会触发merge
。
2. 系统有后台线程会定期merge
。
3. 执行数据库关闭操作的时候,也会执行merge
操作。
change buffer
和redo log
的区别
change buffer
主要用于减少读磁盘的次数,在必要时更新数据。redo log
则是减少内存更新后,写磁盘的次数。InnoDB
支持覆盖索引,即从辅助索引中就可以得到查询的记录,则不需要查询聚集索引中的记录。
select id,b from t where b=xxx
此时id为主键,b为索引
由于覆盖索引可以减少搜索的次数,显著提高查询性能,所以索引覆盖是一个常用的性能优化手段。
以最左边为起点任何连续的索引都能匹配上。
1. 如果第一个字段是范围查询需要单独简历一个索引
2. 在创建多列索引时,根据业务需求,where自居中使用最频繁的一列放在最左边
where
语句中包含or
时,可能会导致索引失效。
如果
or
条件中包含非索引,就会使用全表扫描。如果两边都是索引,就会使用index_merge
的优化技术。
where
语句中索引如果使用了负向查询,可能会导致索引失效。
Not
、!=
、<>
、!<
、!>
、NOT IN
、NOT LIKE
等。
对索引列进行运算,则一定会导致索引失效。
SELECT * from T where ID+1 = 3
在索引列上使用内置函数,一定会导致索引失效
SELECT *, SUBSTR(materiel_id,10) from container_load where SUBSTR(materiel_id,10) = 852729344
为满足最左匹配原则
select * from t where k2=2;
select * from t where k3=3;
slect * from t where k2=2 and k3=3;
// 以下这条只会部分走索引
slect * from t where k1=1 and k3=3;
undo log
主要有两个作用:回滚和多版本控制。
在数据修改的时候,不仅记录了redo log
,还记录了undo log
,如果因为某些原因导致事务失败或者回滚了,可以使用undo log
进行回滚。
1. 保证事务进行rollback
时的原子性和一致性。undo log
主要存储的也是逻辑日志,比如我们需要insert
一条数据,那么undo log
会记录一条对应的delete
日志。我们要update
一条记录时,他会记录一条相反的update
记录。
2. 用于MVCC
快照读的数据,在MVCC
多版本 控制中,通过读取undo log
的历史版本数据可以实现不同事物版本号都拥有自己独立的快照版本数据。
MySQL
里长说道WAL(WriteAheadLogging)
技术,他的关键点就是先写日志,在写磁盘。
InnoDB
引擎就会先把记录写到redo log
里面,并且更新内存,这个时候更新就算是完成了,同时InnoDB
会在闲暇的时候将操作记录更新到磁盘当中。InnoDB
的redo log
的大小是固定的,采用循环写入的方法进行写操作。