mysql考点

参考:

1、B树和B+树的区别?

​ 1、b+ 树 在 叶子结点之间有指针,而b 树 没有,mysql 是双向指针。这是b+ 树 范围查找 强于 哈希、b树 的关键!

​ 2、b+树 数据都在 叶子结点,b树 每个结点都有数据,b+树每个结点内都是 索引,可以放很多,因此分叉就多,b+树的高度就能被控制在小的范围内。

​ 3、b+树 索引 会重复,b树的 索引 是不会重复出现的。

2、B+ 树 是怎么产生的?

​ 首先,每一个页(叶子结点)按照如下方式设计;截屏2022-10-14 18.47.46

​ 以上 用户数据 按照 顺序递增 加入链表,(所以最好用自增顺序加入数据,不然链表的中间插入操作 复杂度高。);用页目录来降低搜索具体数据的复杂度; 页头中有两个指针 ,来连接 首尾叶子结点。

​ 然后,如同 用页目录 简化 数据链 搜索复杂度的 思路,在不同叶子结点上面用 一个新的结点,只存放每个 叶子结点的 首 数据,来简化 搜索 叶子结点链表 的复杂度,如下:

截屏2022-10-14 18.55.32

​ 依次类推,一层一层往上,搭建起一个 b+ 树。

​ 假如一个 索引 由一个 int类型的数据结构和一个指针组成,int 是 4b(4字节)innodb指针 是 6b,一个索引就是10b;

​ 一个结点 是 16kb,一个结点纯放索引可以达到 16kb /10b =1638个索引。

​ 假如 一个记录 是1kb,那么叶子结点 能存 16kb / 1kb=16条记录,一个索引 就能查到 16条记录,两层情况的 b+ 树 理论可以存放 1638 * 16 = 26208 条记录。

​ 以此类推,三层的b+ 树 可以存 1638 * 1638 * 16 = 42928704(4千万)记录。

3、Innodb是如何支持范围查找能走索引的?

​ 1、走索引;

截屏2022-10-14 20.03.01

​ 2、走全表查询;

截屏2022-10-14 20.03.54

​ 3、先走索引,再 走叶子结点查找,是范围查找的主流做法。

4、为什么要遵守最左前缀原则才能利用到索引?

截屏2022-10-14 20.18.57

​ 因为 在覆盖索引(联合索引) 中,结构类似于多级目录,一定在要保证 一级目录有序的前提下,二级目录才能有序,以此类推;

​ 如果直接 没有 左边的索引,直接用右边索引 ,因为无序会找不到索引。

​ 只要 where 后面有 索引,顺序不是 和联合索引一样没关系,mysql 会自动调优成 索引顺序。 where c and a and b; 是复合最佳左前缀的。

​ 另外,(1号位置、3号位置)也是可以走索引的,先利用 1号位置找到 叶子结点,再 用3号位置 索引条件下沉 直接 在 b+树中 判断好 ,再 一次性去聚集索引(主键索引)中回表查询。

5、范围查找导致索引失效原理分析

​ “走 索引、再走回表查询 所造成的 io消耗 +cpu 消耗” > “走 全表查询 的io 消耗 + cpu消耗”。

​ 此时,mysql 会自动选择最优的 方法。就可能 范围查找 索引失效了,cpu 开销单位0.2,io 开销单位1.0。

​ (一)走全表查询 开销:

​ 通过 show table status like '表名' 可以 查看到 Data_length,通过 show table status like '表名' 可以 查看到 Rows, data_length/1024/16 = 结点数量, 结点数量 * 1 = io 开销;

​ rows * 0.2 = cpu 开销;

​ (二)走索引开销:

​ 先用1.0也就是常数级开销找到起始索引位置,再把范围内 x 个叶子结点对应的主键加载进内存,然后去回表查询。

​ x * 1.0 + 1.0 = io 开销

​ cpu 二级索引中 读取这 x 个数据一遍,回表查询再 读一遍。

​ x * 0.2 + x * 0.2 = cpu 开销

​ 比较(一)(二)总的谁小,mysql 会自动选小的,可以就导致了范围索引失效了。

6、覆盖索引的底层原理

​ select 要找的 字段 直接就是 索引 中的一员,或者就是 二级索引中叶子结点中存放的 数据,不用去 回表查询了。也就是select 要找的 直接被 索引覆盖住了。

​ extra 会是 using index。

7、索引扫描底层原理

​ b 是二级索引的一员

​ select b from t;

​ 连 where 都没有,只可能走叶子结点从左至右遍历,也可能走索引。

​ mysql 会考虑两种 遍历,一种是 走主键索引的叶子结点遍历,遍历的是全数据;另一种 是走 b 所在的二级索引的叶子结点遍历,遍历的是一批索引 而已,不是全数据,因此可能快很多。

截屏2022-10-14 21.04.54

截屏2022-10-14 21.05.11

8、order by为什么会导致索引失效?

截屏2022-10-14 21.10.30

​ 都是走 遍历叶子结点 的方向,走二级索引还不用排序,但是 回表8次,全表扫描的话,对全部数据 加载进 内存,然后内存排序(数量不多的话可能很快),不用回表,数量不多的话,mysql 会选择一个 最优的,可能是全表扫描。

9、mysql中的数据类型转换有哪些要注意的?

截屏2022-10-14 21.23.27

​ 以上 a字段是 int类型,e字段是 str类型;

​ mysql 中 只要 类型对不上都会强制类型转换,但是不是转ascii码,而是无论=左边还是右边,统一 str 转成 数字 0,但是 ‘123’、‘23’ 、‘9’ 这样的数字字符串 会被转成 123、23、9 这样对应的数字。

​ 以上的 最后一个 式子中,e = 1,等式左边e 是 str 类型,右边是 int 的1, e字段中所有的索引都被自动转成了 0,e 要把b+ 树结构都改了,开销会非常大,mysql权衡利弊,最后根本没有用到索引,直接用全表扫描。

10、对字段进行操作导致索引失效原理

​ e 是索引

​ where e = 1,等式左边e 是 str 类型,右边是 int 的1, e字段中所有的索引都被自动转成了 0,e 要把b+ 树结构都改了,开销会非常大,mysql权衡利弊,最后根本没有用到索引,直接用全表扫描。

11、Mysql中有哪些存储引擎?

​ 这些存储引擎 是针对 表的,叫 表存储引擎。

​ innodb、myisam、memory、csv。

12、MyISAM和InnoDB的区别是什么?

截屏2022-10-14 21.43.29

13、数据表设计时,字段你会如何选择?

截屏2022-10-14 21.47.45

截屏2022-10-14 21.48.58

截屏2022-10-14 21.49.20

14、Mysql中VARCHAR(M)最多能存储多少数据?

截屏2022-10-14 21.51.58

15、请说下事务的基本特性?

截屏2022-10-14 21.54.18

16、事务并发可能引发什么问题?

​ 脏读(别人提交前,被你读了)、不可重复读(读第一次,别人update了,你读第二次)、幻读(读第一次,别人insert了,你读第二次)。

17、简单描述下Mysql各种索引?

​ 主键索引、唯一索引(多个null不会冲突)、普通索引、前缀索引(取很长的str的前几个字符作索引)。

18、什么是三星索引?

截屏2022-10-14 22.07.18

19、InnoDB一颗B+树可以存放多少行数据?

​ 约 2千万。

截屏2022-10-14 22.10.30

​ 前面在 b+ 树是怎么产生的疑问中,我们已经推过了,但是实际上innodb 中不是int类型,而是bigint类型,长度是8 ,因此是 2千万左右。

20、如何提高insert的性能?

​ 1、合并 多条 insert 为一条,减少日志量;

​ insert into t values(a,b,c),(d,e,f)…

​ 2、bulk_insert_buffle_size 调大批量插入缓存;

​ 3、innodb_flush_log_at_trx_commit = 0;

​ 4、手动提交事务,减少io。

21、什么是全局锁、共享锁、排它锁?

​ 共享锁(读锁):本会话只能对其读不能写,对其他表不能任何操作;其他会话可以来读,不能来写。

​ 排它锁(写锁):本会话能 对其 增删改查,不能对其他表或者行 任何操作,其他会话不能对锁上的对象有任何操作。

​ 全局锁: 库逻辑备份时,整个库都处于 只读状态。

22、谈一下Mysql中的死锁

​ 两个或者两个以上的进程,争夺资源而相互等待的现象。

show engine innodb status 查看最近一次死锁;

innodb lock monitor 锁监控;

​ 死锁怎么办? 应该超时等待时间 innodbblockwait_timeout

​ 发现死锁后,把一个事务回滚,让其他事务继续执行。

23、Mysq如何实现读写分离

​ 将mysql 的数据拷贝成多份 写到其他mysql 服务器上,原来mysql 的数据库负责写,称为 “主库”,其他的数据库 负责读,称为 “从库”。

截屏2022-10-15 17.50.05

​ 用了 binlog 日志文件,开了一个log dump 线程在主库,从库中用一个io线程接收,搞了一个依赖日志 relay log,把主库的修改同步来过。

​ 优点:1、部分宕机,也不会全部完蛋;

​ 2、分开读写,性能更优;

​ 缺点:mysql 的读写分离是 异步 的,异步就是 不管结没结到 反馈,这边只管发送 ,容易导致 数据的丢失,和 kafka 的异步 丢数据类似。

24、Mysq如何实现分库分表

​ 根据 业务 “垂直拆分”:例如 将不同的表根据“业务”分别放进 用户库、内容库…

​ “水平拆分”: 将单一的数据表,按照某一种规则,放进多个数据库或者多张数据表当中,例如 用 hash 取模 的规则 将 用户表 放进多个 用户库中1、2、3….; 例如 按时间 每个月的数据 放到每个月的库中。

​ 有时候分库分表也会带来一些问题,比如说 以后查询 某个数据,需要跨多个库和多个表,我们引入 mycat 、等工具解决。

25、索引的基本原理

​ 类似于 新华字典 的目录的作用,具体说一下 hash 、b+ 树就好了。

26、mysql聚簇和非聚簇索引的区别

​ 聚族索引:索引找下去能找到 存在叶子结点的 真实数据;而且一定是顺序存储的。

​ 非聚族索引: 索引 找下去 ,叶子结点 存的 也是 索引,找真实数据要回表查。

​ innodb 主 是聚族索引, myisam 是 非聚族索引存的都是 索引信息,所以 innodb 在范围查找占优,而大范围的排序或者全表扫 myisam 优;

​ 总体innodb 强于myisam。

27、mysql索引结构,各自的优劣

​ 主流的就是 b+ 树、其次 如果仅仅是单条查询,还可以用 hash。hash 面对大量重复值 ,存在大量的冲突,效率低,而且不支持范围操作,而b+ 树牛逼多了。

28、索引的设计原则

截屏2022-10-15 18.31.37

29、mysql锁的类型有哪些

​ 共享锁、排它锁、

​ 表锁、行锁、全局锁

​ 意向共享锁、意向排它锁(这两个都是表锁无法手动创建,目的是通过预告降低尝试的操作次数。)、

​ 行锁下又包括: 记录锁、间隙锁、临键锁(左开右闭)。

30、mysql执行计划怎么看

​ 就是说说 explain select… 出现的各个指标的意义。

​ id)

​ explain结果里 id有相同也有不同,id大的优先,然后在id值相同的从上往下顺序执行。

​ (select_type)

​ 里、外、中,join 等。

​ type)索引类型、类型。

​ const : 仅仅能够查到一条数据,用于primary key 或者 unique索引。eq_ref: 唯一性索引,对于每一个索引键的查询,返回匹配唯一行数据。ref: 非唯一性索引,对于每个“索引键”的查询,返回匹配的所有行 (0或者多个)。 range:检索指定范围的行,where后面是一个范围查询(between、<、>、in有时候会失效转为无索引情况。)index:把所有索引都查一遍。all:把所有字段都查一遍。

​ (possible_keys)可能用到的索引

​ key)实际用到的索引

​ (key_len)索引的长度,用于判断复合索引是否被完全使用。

​ (ref)表明当前表所参照的字段。

​ (rows)实际通过索引扫描的 数据个数(注意是取交并集之前就扫描了)。

​ (Extra)

​ using filesort:性能消耗大,需要“额外”一次排序(或者 查找),常见于order by 出现时。using temporary:性能损耗大,用到了临时表。常见于 group by 出现时。using index 性能提升。索引覆盖。using where 需要回表查询。impossible where 不可能出现的情况。

31、事务的基本特性和隔离级别

​ 原子性(都成功都失败)、

​ 一致性(事务的约束条件不能打破,90块钱不能买100块东西)、

​ 隔离性(提交前对别人不可见)、

​ 持久性(一旦提交永久保存);

​ 隔离级别:

​ read uncommit 容易脏读

​ read commit 别人一改它就读了,可能前后不一致的 不可重复读

​ repeatable read (默认)总读第一次读到的,不管别人改没改,可能 幻读,因为别人insert 了

​ serializable 最死板,每个读都加锁不让别人操作,效率低。

32、怎么处理慢查询

​ 看看原因:临时开 set global slow_query_log=1;查看mysql / data / 慢日志文件。

​ 1、没命中索引? explain

​ 2、查了不需要的字段?

​ 3、数据量太大? 横向、纵向业务分表。

33、ACID靠什么保证的

​ innodb 表引擎用如下方法保证:

​ 原子性 用 undolog 日志保证;

​ 一致性 业务上保证;

​ 隔离性 mvcc 保证;

​ 持久性 内存+ redolog 日志 保证,宕机后从redolog 日志取数据恢复;

redolog 写盘 – 事务进入prepare状态 – binlog 写盘 – 持久化到 binlog – 如果成功 事务进入 commit 状态 – redolog 写入一个 commit;

34、什么是MVCC

截屏2022-10-15 21.15.03

     在 read commit 和 repeatable read 两种隔离级别才有 mvcc,读未提交的话根本不存在版本号,串行化全是锁 用不上;

截屏2022-10-15 21.19.08

截屏2022-10-15 21.32.21

      找到字段最新版本号trx_id ,如果在readview 或者它的左边就可以直接用,如果在readview 右边也就是版本号比 readview 大,则不可用, 如果不可用就回到 字段的 roll_point 链上去找上一个版本,重复这样的判断。

​ read commited 隔离级别下,readview 不断的生成,可能导致前后读的内容 发生了变化,而 repeatable read 隔离级别下,事务内都用第一个readview作后面出现的此字段的readview 来保证可重复读;

35、mysql主从同步原理

截屏2022-10-15 21.43.57

截屏2022-10-15 17.50.05

截屏2022-10-15 21.48.24

​ 这个和kafka 有点像。

36、简述Myisam和Innodb的区别

截屏2022-10-15 21.51.24

截屏2022-10-15 21.53.56

37、简述mysql中索引类型及对数据库的性能的影响

截屏2022-10-15 22.00.14

38、什么是倒排索引?

截屏2022-10-15 22.53.56

39、Mysql数据库中,什么情况下设置了索引但无法使用

​ 1、没有符合 “最左前缀”原则;

​ 2、字段类型进行了 隐式转换,如 str 转 int 全部要变成 0,mysql就没走索引;

​ 3、全表扫描 开销 小于 走索引加回表查询 的 开销;

40、B树和B+树的区别,为什么Mysql使用B+树

截屏2022-10-15 23.03.28

​ 结合前面讲的 ,画个图。

41、乐观锁、悲观锁

​ 行锁、表锁、等等都是悲观锁,真的锁住了;

​ 乐观锁 不会真的是 锁住 行和表,而是通过版本控制mvcc的方式。