浅谈mysql底层索引

索引

B+树特征:数据全部放在叶子结点,并且按照索引字段递增排序。

扫描表的方式:

  1. 全表扫描
  2. 辅助索引+回表

假如一张表有abcde五个字段,a为主键。
在innodb中,一页默认是16KB。有如下

  1. 主键索引
    每一行都有隐藏的rowID,没有设置主键时,rowID则变成主键。
  2. 联合索引
    假如bcd三个字段联合索引, **回表的意思是通过联合索引查出来的主键,再通过主键索引查询数据。 **
    MySQL5.7以前会回表多次,
    5.7及以后做了优化会回表一次。
    索引的最左前缀原则

因为bcd三个字段不是主键,有可能重复,所以B+树索引的非叶子节点除了bcd字段还保存着主键。

null值是最小的

innodb(聚集)

下图是数据页格式和innodb行格式,dynamic是默认格式


下图是聚集索引:叶子结点包含了所有的数据记录

  • .frm 表结构
  • .ibd 数据+索引

为什么innodb必须要有主键,并且推荐主键时整型且是自增的?

答:innodb要有主键索引,并且innodb底层是B+树,非叶子节点存储的是主键,在查找时要比较主键大小,整型比字符串效率高。自增可以避免叶子结点作分裂以及自动平衡。

为什么非主键索引的叶子结点存储的是主键值?

答:一致性和节省存储空间。

myisam(非聚集)

堆表:查询时和插入顺序一样

表的引擎设为myisam时,会生成三个文件,

  • .frm 表结构
  • .MYD 存数据的
  • .MYI 存索引的

事务

四种隔离机制:

读未提交:A B开启事务,A修改字段还没有commit,B就可以查看到。这是脏读。

读已提交:A B开启事务,A修改字段,commit之后,B才可以查看到。这是不可重复读。A添加字段,commit之后,B才显示多了一条数据。这是幻读。

不可重复读:A B开启事务,A修改字段,commit之后,B也commit之后才可以查看到。 读的不会发生幻读了(因为有MVCC机制),MySQL已经对其进行了优化。

MVVC机制

版本链和readview

readview中有m_ids,当中保存的是活跃的事务id, 别的事务会读取最新的已提交的数据。读已提交和不可重复读的区别见下图。

MVCC机制(下图重要)

锁机制

表锁(Myisam)



总结:

  • 偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发最低。
  • 偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

表锁(innodb)

在读已提交隔离级别下

事务提交之后,锁就释放。
查询时使用的是主键或者唯一索引,只会锁那一行数据。

查询时使用普通索引,会对查询出来的所有行加锁,其他行没加锁。

查询时没有使用索引,也会对查询出来的所有行加锁,其他行没加锁。 再添加数据不会阻塞

在可重复读隔离级别,下会加入间隙锁

在普通索引下,例如e字段的索引,如果已经对e=2的记录加了锁,则也会对其间隙也加上锁。新插入间隙上的记录会阻塞,不在间隙上不阻塞;若e>2,则对大于2的全部加锁了。, 这是避免了幻读。

查询时,该字段没有使用索引(也就是全表扫描),也会对查询出来的所有行加锁,其他行 包括间隙 也都加了锁。 再添加数据会阻塞,也避免了幻读。

分析系统中的行锁争夺情况

varchar类型字段不加单引号‘’会强制类型转换,从而会是行锁升级为表锁。---这是真的?

索引优化

extra中的using filesort和using temporary是最不好的。
using index 好!

覆盖索引:

优化

 **单表**:范围查询时,where a>1 后面的条件用不到索引。详情见最左前缀原则。

 **两表** :使用join,是 left join 则在右表相应字段建立索引。是 right join 则在左表相应字段建立索引。

三表 :记住:永远用小表驱动大表。

索引失效的情况

第8条:like要是必须得有%,则必须使用覆盖索引。即select字段必须存在索引。


查询优化

小表驱动大表

order by排序优化

使用最左前缀原则

group by 查询优化

和order by一样

慢查询日志

批量插入数据

主从复制

修改my.ini文件

一主一从常见配置

停止从服务复制功能:`stop slave;`

  • 主机建立账户并授权slave

  • 从机配置需要复制的主机

posted @ 2020-03-08 22:05  奕峰  阅读(295)  评论(1编辑  收藏  举报