小林coding | MySQL图解
三,索引篇
什么是索引?
此时【索引】 就是目录。主键索引就是根据主键建立的目录。索引(目录)的建立在建表插入数据的时候就已经存在了。
为什么 MySQL InnoDB 选择 B+tree 作为索引的数据结构?
B Tree在哪一层查到不确定,查询效率不稳定
二叉树 层数会很多
B+Tree查询效率高
联合索引
执行这个语句,会建立一个B+Tree的索引(目录)
最左匹配原则
最左边的必须在
(A,B,C)联合索引,索引 (A, B, C) 的物理存储顺序是 A -> B -> C。必须是(A)(A+B)。(A+C)(B)(C)不行
从数据页的角度看B+树
就是以前os中磁盘里的数据是如何存储的知识,太麻烦了跳。
MySQL 单表不要超过 2000W 行,靠谱吗?
此时树高为3。
索引失效有哪些?
失效了就要进行全表扫描
- 对索引使用左或者左右模糊匹配
因为B+Tree索引表是按照【索引值】有序排列在B+Tree上的,只能根据前缀进行比较 - 对索引使用函数
- 联合索引非最左匹配
- WHERE 子句中的 OR
count(*) 和 count(1) 有什么区别?哪个性能最好?
- count()函数是什么?
函数指定的参数不为 NULL 的记录有多少个。
- count(主键字段)的执行过程。(字段 值 如果不是NULL就统计下来)
有主键索引没有二级索引 遍历主键索引
没有主键索引有二级索引,遍历二级索引。(因为二级索引的叶子结点中记录更小)
- count(1)与count(*)没有任何区别,就是统计表中有多少条数据的
MySQL 分页有什么性能问题?怎么优化?
数据库的分页会出现【深度分页】的 性能问题。就是读1000页,必须扫描前面1,2,3。。。。999.
只查前几页 ,就不叫【深度分页】。
[分页查询]的关键字是 order by id limit offset,size;
分页的sql语句是
select * from [表名]
order by id limit offset,size;
1.主键索引时【分页查询】的优化
这样就不会把0~600w从存储引擎拿到SQLserver层中,优化了拿到server层的部分
2.非主键索引时【分页查询】的优化
优化了回表
3.除了1.2在语法上进行优化,还可以在产品上进行优化。如抖音的【瀑布流】
4.分批获取的方式通过 WHERE id > ? LIMIT n
四,事务篇
事务隔离级别是怎么实现的?
- 【读未提交】 顾名思义读到未提交的数据
- 【读提交】 读提交了的数据
- 【可重复读】 有一个readview(约等于在启动事务的时候拍了一张快照),事务中读的是快照,提交事务后才是正常读
- 【串行化】 没有了并行,事务都是串行执行
MySQL 可重复读隔离级别,完全解决幻读了吗?
解决方案有两种
这个例子就是用快照读Read View,无法完全避免幻读。
快照查 是查看事务开始时的快照副本
当前读 是读取最新的正本并上锁
五,锁
MySQL中要理解锁,首要的是有【读锁】【写锁】的概念。全局锁,表锁,行级锁都是围绕这个展开的
全局锁
全局锁+【可重复读】=实现全库备份
表级锁
- 表锁
//直接当成读锁理解就行(共享锁)
lock tables t_student read;
//写锁(独占锁)
lock tables t_student write;
-
元数据锁
-
意向锁
不懂
行级锁
-
Record Lock记录锁。
-
Gap Lock间隙锁
防止幻读
-
Next-Key Lock
-
插入意向锁
事务A中是Next-Key Lock,事务B因要在中间插入一条记录。所以Next-Key Lock会阻塞B,B怎么被阻塞了,就是插入意向锁起的作用。
MySQL 是怎么加锁的?
具有加锁行为的语句
update,delete,select...for update
当等值查询(where)查到时 ,对索引加上记录锁
当 等值查询(where)没有查到时 ,对索引加上 间隙锁
如果带有加锁行为的语句没有走索引,进行了全表查询,会把全表都锁住,造成巨大消耗。
MySQL 死锁了,怎么办?
为什么会产生死锁?
同这个段子一样,发生了死锁!!!
如何避免死锁?
- 设置这些锁的超时时间。超过一段时间,自动回滚到事务未开始的时候。
- 开启 主动死锁检测。 发现死锁直接消灭。
六,日志篇
为什么需要 undo log?
回滚
在执行事务时,在undo log中记录。
比如我是deleteXXX,undo log中就会记录deleteXXX
需要回滚时,就反着执行插入
为什么需要 redo log ?
持久化(防止断电)
WAL(write-ahead log)技术,写入磁盘写,先在log上写。
比如 我执行deleteXXX,redo log就会记录在哪儿做了deleteXXX的更新。