基础相关
表引擎
默认使用InnoDB引擎,常用的还有Memory引擎、MyISAM引擎。
Memory引擎通常作为Mysql中间表的引擎,存放查询的中间结果。
InnoDb与MyISAM的区别
| 类型 | MyISAM | InnoDB |
|---|---|---|
| 事务 | 不支持 | 支持 |
| 锁 | 支持表级锁 | 支持行级锁 |
| 并发控制 | 不支持 | 支持(MVCC) |
| 外键 | 不支持 | 支持 |
| 全文索引 | 支持 | 不支持 |
| 数据缓存 | 不支持 | 支持 |
事务
特性
- 原子性:所有操作要么成功,要么回滚
- 隔离性:事务之间相互隔离,不受影响
- 一致性:执行事务前后处于一致性状态
- 持久性:事务提交之后就是永久操作
隔离级别
- Serializable(串行化)
- 最高级别,可避免幻读、不可重复读、脏读,事务串行执行
- Repeatable Read(可重复读)
- 可避免脏读、不可重复度。
- Read Committed(读已提交)
- 可避免脏读
- Read uncommitted(读未提交)
- 最低级别
注:
- Mysql默认隔离级别为可重复读,使用MVCC及间隙锁解决幻读
- Oracle默认隔离级别为读已提交
- 不可重复读的重点是修改,相同的条件,你读取过的数据,发现在读取一次不一样了
- 幻读的终点是新增或者删除,相同的条件,第一次和第二次的读出来的结果不一样(增加或减少)
- Mysql中有行级锁(间隙锁)、表级锁、共享锁(读锁)、排它锁(写锁)、乐观锁(MVCC)
高可用架构
BinLog录入格式
- statement
- 记录单元为语句,每一条sql造成的影响都会记录,使用了函数的sql语句不记录
- row级别
- 记录单元为每一行的改动
- mixed
- 二合一,普通操作使用statement,无法记录的使用row,新版本的mysql做了优化,表结构变更只会记录语句,不会记录所有行。
主从同步
使数据从主数据库服务器复制到其他从服务器上,只有一个主服务器,其他都是从服务器,通常为异步复制,利用binlog进行同步
读写分离
就是写主库,读从库,主库只提供写服务,读请求由从服务提供。
为什么要进行主从同步
通过从服务器复制主服务器的完整数据,提高数据的安全性,增加了整个数据库服务的性能。
主从复制流程
master节点中所有的操作被记录在binlog中,salve拉取master的binlog日志,放入自己的relay中,salve执行relay log中的sql语句进行同步数据。
主从同步复制延迟如何解决
mysql有两个复制的机制
- 半同步复制
- 用来解决主库数据丢失问题,主库数据写如binlog后会立即将数据同步给从库,从库成功将数据写入本地relay log后会返回主库一个ack,主库至少接到一个从库返回的ack才认为此次数据写入成功。
- 并行复制
- 从库并行读取主库的binlog日志,库级别的并行
查询优化
join优化
一般优化驱动表,驱动表是指当指定或未指定查询条件,满足查询条件记录行数较少的一个表就叫驱动表。
一般在被驱动表上建立索引优化。
- 左连接(left join),通常左表为驱动表,右表为被驱动表,在右表建立索引优化查询
- 右连接(right join),通常右表为驱动表,左表为被驱动表,在左表建立索引优化查询
- 内连接(inner join),小表驱动大表,在大表建立索引优化查询
大表数据查询优化
- 优化表结构,热点字段建立索引,利用expain优化sql语句
- 利用缓存
- 读写分离
- 分表,垂直拆分(拆表字段),水平拆分(分表)
超大分页优化
利用延迟关联或子查询进行优化
例如1:
优化前: select * from table from age>20 limit 1000000,10
优化后: select * from table where id in (select id from table where age > 20 limit 1000000,10)
原理:对age字段建立索引,利用索引覆盖,优化查询速度
例如2:
优化前:select * from table from age>20 limit 1000000,10
优化后:select * from table a inner join (select id from table where age > 20 limit 1000000,10) b on a.id = b;
原理:延迟关联,在索引列上分页,再回表查询数据
索引
索引的种类有哪些
- 存储结构来划分
- BTree索引(B-Tree和B+Tree),Hash索引,full-index全文索引,R-Tree索引
- 应用层次划分
- 普通索引,唯一索引,复合索引,主键索引
- 数据与索引的关系
- 聚簇索引,非聚簇索引
注:
- R-Tree索引:空间数据存储的树,常用于坐标搜索,类似的有geohash
- B+Tree相对于B-Tree的区别,只有子叶结点存储数据,每个子叶结点都有一个指向下一个数据的顺序指针。
索引是如何工作的
Mysql分为聚簇索引(主键)和非聚簇索引(二级索引)
- 聚簇索引的B+Tree子叶结点会保存完整的数据
- 非聚簇索引的B+Tree子叶结点只会保存数据的主键 在设置了二级索引的情况下,在查询过程中,查询条件为二级索引,那么首先从二级索引的B+Tree中找到符合查询条件的数据的主键,在去主键的索引中通过主键获取完整的数据,这个过程也叫做回表。
为什么设置了索引,查询也不一定会走索引
- 查询条件中索引列涉及函数计算
- 查询中不包含联合索引的第一列
- 后缀匹配查询
- 因为查询优化器,mysql查询优化器会根据表信息(行数、数据大小)来对使用和不使用索引的查询做策略判断,具体是IO操作及CPU耗时,选择最优的方式进行查询,通过开启optimizer_trace=enable=on来查看优化器生成执行计划的过程。
什么是做引覆盖,什么是回表
- 如果我们查询的数据是索引列或者联合索引覆盖的列,那么查询索引本身就是需要的数据,就不需要进回表查询,这种情况就是索引覆盖。
- 回表指,通过二级索引或者数据的主键,在利用主键去查询完整的数据,这个过程叫回表。
索引实现为什么使用B+Tree而不是BTree
定义
- BTree 允许每个节点有更多的子节点
- B+Tree 所有数据存储在叶子节点中,非叶子节点不存储数据,所有叶子节点都有一个顺序指针。
原因
- B+Tree的查询效率稳定为O(logn),BTree的查询效率不稳定,最好为O(1),最差为O(logn),B+Tree更适合区间查询的情况
- 由于B+Tree只有叶子节点保存完整的数据,那么相同条件的查询情况下,B+Tree的IO操作会比BTree少的多,因为B+Tree包含更多的索引。
B+Tree索引与Hash索引的区别
- Hash索引适合等值查询,无法进行范围查询
- Hash索引没办法通过索引进行排序
- Hash索引不支持联合索引的最左匹配原则
- 如果有大量key值重复的情况下,Hash索引效率很低,因为会有Hash碰撞
注
Hash碰撞解决方案:
- 开放地址法,常见实现为线性探测法,简单理解就是产生冲突时,增加增量序列直到不冲突为止
- 拉链法,HashMap解决Hash碰撞的方法,即产生冲突时产生一个链表,将相同hash的值都放在链表中,俗称套娃。
- 再Hash法,就是增加变量进行hash计算。
联合索引
- 联合索引遵循最左匹配原则,但是会在范围查询或者后缀匹配查询时失效
- 优化器会自动调整查询参数位置以便使用联合索引进行查询
- 区分度高的字段放在最左边,反之(性别字段等)放在后面
- in查询也可以乱序,优化器会优化参数位置。
什么是索引下推
mysql5.6中引入,设置optimizer_swich = 'index_condition_pushdown=off'可以关闭,InnoDb引擎默认开启,可以减少回表次数,只针对二级索引。
explain
使用explain查看sql执行计划
-
type:字段是判断查询是否高效的重要依据,性能关系如下:
- All<index<range~index_merge<ref<eq_ref<const<system
-
rows:字段代表扫描行数,原则上rows越小越好
-
possible_keys:字段代表可能有利于查询效率的索引字段
-
table:代表查询涉及的表
-
key:代表使用的索引