文章目录
MySQL的存储引擎
提示:MyISAM和InnoDB的区别
常用的就是MyISAM和InnoDB
MyISAM只支持表级锁,而InnoDB支持表级锁和行级锁;
MyISAM不支持事务,外键,而InnoDB支持
MySQL索引使用的是什么数据结构?
使用的是B+树,因为B+树只有叶子结点才存储数据,叶子结点之间使用链表进行关联,范围查询效率相对较高。
B+树的结构是什么,跟B树有什么区别?
B树的数据结构是每个对应的索引列的值上存放对应的数据。
而B+树只会在叶子节点上存放对应的数据,而非叶子结点只存放索引列的数据
为什么InnoDB选择B+树来作为索引?
因为就是为了减少磁盘io次数,因为b+树所有最终的子节点都能在叶子节点里找见, 所以非叶子节点只需要存索引范围和指向下一级索引(或者叶子节点)的地址
就行了, 不需要存整行的数据,所以占用空间非常小,直到找到叶子节点才加载进来整行的数据。
什么是回表?
针对非聚簇索引,因为非聚簇索引的叶子结点上存储的主键和当前索引列的值,当一个select语句返回字段中包含没有索引的字段时候会进行二次查找,这里可以使用覆盖索引来避免回表,提高查询速度。
事务的基本特性
原⼦性
(Atomicity): 一个事物中的操作要么全部完成,要么完全失败,原子性是由undo log日志来保证的,因为undo log日志记载着数据修改之前的信息。⼀致性
(Consistency): 执⾏事务前后,数据保持⼀致,多个事务对同⼀个数据读取的结果是相同的;- 一致性是我们使用事务的一个目的,而原子性,隔离性,持久性都是为了保障一致性的手段。
隔离性
(Isolation): 一个事物的修改在提交之前对其他事物是不可见的- 隔离性指的是在事务并发执行的时候,他们内部的操作不能互相影响,如果多个事务可以同时操作同一个数据,那么就会产生脏读,幻读和不可重复读的问题
- 而那个事务的隔离级别的话有读未提交,读已提交,可重复读和串行化。不同的隔离级别对事务之间的隔离性是不一样的,级别越高隔离性越好,性能就越低
持久性
(Durability): ⼀个事务被提交之后,所做的修改就会保存到数据库中,数据库底层采用的是redo log来持久化数据
事务的隔离级别
read uncommit
(读取未提交): 一个事务可能会读到其他事物未提交的数据,也叫作脏读。read commit
(读取已提交):是指一个事物提交之后,它做的变更才会被其他事物看到。也叫作不可重复读。repeatable read
(可重复读): 是指一个事物在执行过程中看到的数据,总是跟这个事物启动时看到的数据是一致的。会产生幻读。- 幻读:幻读指的是一个事物可能在多次读取期间会看到其他事物所插入的数据
serializable
(串⾏化): 是事务的最⾼的隔离级别。事务和事务之间执行是串行的,但是效率低下比较耗数据库性能,一般不推荐使用。
你线上使用的是什么隔离级别?
用的是读已提交的隔离级别,mysql默认的是采用可重复读,可重复读可能会因为间隙锁而导致死锁问题。因为一开始MySQL的binlog没有row模式,在读已提交的模式下会产生数据不一致的问题。
- binlog记录的就是数据库表结构和表数据所做的更改。
Mysql的锁有哪些
提示:根据锁的粒度划分
MySQL默认使用InnoDB引擎的,而在该引擎下根据锁的粒度可以简单分为行锁和表锁。而行锁又可以划分成读锁和写锁。读锁是共享的,多个事务可以读取同一个资源,但不允许其他事物在读的时候进行更改。写锁是排它的,因为写锁会阻塞其他事物的写和读的操作。而表锁的话是锁的整个表。
索引的分类
索引是帮助MySQL高效获取数据的数据结构。常见的索引类型有普通索引,唯一索引,主键索引,全文索引和组合索引。
- 普通索引:允许加了索引的列包含重复的值
- 唯一索引:索引列的值必须唯一,允许有空值。
- 主键索引:一个表只能有一个主键,不允许有空值
组合索引
:指的是在多个字段上创建的索引,只有在查询条件中使用了创建索引的第一个字段,索引才会被使用,它遵循最左前缀原则。(比如a,b,c 组合索引,a,ab,abc会全部使用,ac只会使用索引字段a,c不会被使用。 )- 全文索引:主要用来查找文本中的关键字
什么情况下适合建索引?
- 在经常需要搜索的列上加上索引可以加快搜索的速度
- 在2个表进行
连接查询
的时候,对连接条件的字段建立索引 - 在经常需要根据
范围进行查询
的列上建立索引,因为索引建好之后在指定的范围内是有序的 - 在经常需要
排序
的列上建立索引,因为索引已经排序,查询的时候可以利用索引的排序加快查询的时间 - 在经常使用
where
字句中的列上面建立索引
什么情况下不适合建索引?
当表中的记录数太少,经常增删改的表,数据列上包含大量的重复信息
SQL优化
- 应尽量避免在 where 子句中使用!=操作符,对字段进行 null 值判断,使用 or 来连接条件,进行函数表达式操作,否则引擎将放弃使用索引而进行全表扫描。
- 考虑在 where 及 order by 涉及的列上建立索引,避免全表扫描
- 在模糊查询的时候,不能前置百分号(条件%);在使用组合索引的时候,必须使用该索引的第一个字段作为条件才能保证系统正常的使用索引
- 编写sql语句中select 时,不要写*,不要返回用不到的字段
谈一下你是怎么用MySQL的索引?
一般来说,当一个表中的数据量过大的时候就应该建立索引。从以下几个方面:
- 在select查询语句的时候,不要写*,要指定返回的字段。判断是否可以用覆盖索引,来减少回表的操作
- 针对where后面有个字段的时候判断是否需要加联合索引,同时要满足最左匹配原则
- 对索引列进行函数操作或者表达式计算会造成索引失效
- 通过写出来的sql语句用explain来查看sql的执行计划,查看自己写的sql走了哪些索引
如何优化一条很慢的SQL
-
先通过慢查询日志定位到具体的那一条sql
1. 配置两个参数来输出慢查询sql * set global slow_query_log = on (开启慢查询日志) * set flobal long_query_time = 1000 (设置sql执行时间超过多少就打印日志)
-
找到慢sql之后就进行explain分析sql的执行计划
主要查看type:索引是否失效
rows:是否扫描了多余的记录
-
分析完之后就到了优化阶段(说SQL优化的一些方向)
- 根据具体情况将sql写成一个复杂查询还是多个简单查询
- 去除sql语句中让索引失效的语句
- 尽量让二级索引实现覆盖索引,避免回表