你最需要的MySql秘籍

230 阅读8分钟

基础相关

表引擎

默认使用InnoDB引擎,常用的还有Memory引擎、MyISAM引擎。
Memory引擎通常作为Mysql中间表的引擎,存放查询的中间结果。

InnoDbMyISAM的区别

类型MyISAMInnoDB
事务不支持支持
支持表级锁支持行级锁
并发控制不支持支持(MVCC)
外键不支持支持
全文索引支持不支持
数据缓存不支持支持

事务

特性

  • 原子性:所有操作要么成功,要么回滚
  • 隔离性:事务之间相互隔离,不受影响
  • 一致性:执行事务前后处于一致性状态
  • 持久性:事务提交之后就是永久操作

隔离级别

  • Serializable(串行化)
    • 最高级别,可避免幻读、不可重复读、脏读,事务串行执行
  • Repeatable Read(可重复读)
    • 可避免脏读、不可重复度。
  • Read Committed(读已提交)
    • 可避免脏读
  • Read uncommitted(读未提交)
    • 最低级别
注:
  1. Mysql默认隔离级别为可重复读,使用MVCC及间隙锁解决幻读
  2. Oracle默认隔离级别为读已提交
  3. 不可重复读的重点是修改,相同的条件,你读取过的数据,发现在读取一次不一样了
  4. 幻读的终点是新增或者删除,相同的条件,第一次和第二次的读出来的结果不一样(增加或减少)
  5. 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索引
  • 应用层次划分
    • 普通索引,唯一索引,复合索引,主键索引
  • 数据与索引的关系
    • 聚簇索引,非聚簇索引
注:
  1. R-Tree索引:空间数据存储的树,常用于坐标搜索,类似的有geohash
  2. B+Tree相对于B-Tree的区别,只有子叶结点存储数据,每个子叶结点都有一个指向下一个数据的顺序指针。

索引是如何工作的

Mysql分为聚簇索引(主键)和非聚簇索引(二级索引)

  • 聚簇索引的B+Tree子叶结点会保存完整的数据
  • 非聚簇索引的B+Tree子叶结点只会保存数据的主键 在设置了二级索引的情况下,在查询过程中,查询条件为二级索引,那么首先从二级索引的B+Tree中找到符合查询条件的数据的主键,在去主键的索引中通过主键获取完整的数据,这个过程也叫做回表。

为什么设置了索引,查询也不一定会走索引

  1. 查询条件中索引列涉及函数计算
  2. 查询中不包含联合索引的第一列
  3. 后缀匹配查询
  4. 因为查询优化器,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碰撞解决方案:

  1. 开放地址法,常见实现为线性探测法,简单理解就是产生冲突时,增加增量序列直到不冲突为止
  2. 拉链法,HashMap解决Hash碰撞的方法,即产生冲突时产生一个链表,将相同hash的值都放在链表中,俗称套娃。
  3. 再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:代表使用的索引