文章目录
一、SQL执行的具体过程
连接器–>分析器–>优化器–>执行器
1.1 连接器
连接器用于建立和数据库的连接,有长连接和短链接两种。
短连接
:由于建立连接时比较耗时,所以建议少用短连接。
长连接
:建立连接时的所有查询缓存都不会删除,长连接积累太多缓存会有问题,需要定期重置。
1.2 分析器
判断语法是否正确
1.3 优化器
select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
对于上面的join操作,既可以先从表t1里面取出c=10的记录的ID值,再根据ID值关联到表t2,再判断t2里面d的值是否等于20。
也可以先从表t2里面取出d=20的记录的ID值,再根据ID值关联到t1,再判断t1里面c的值是否等于10。
这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择哪种方案。
1.3 一条查询语句的执行过程
select * from T where id=3;
如果没有索引,就会先取第一条数据,判断id是否等于3,然后再取下一条,依次遍历。
二、数据库的更新操作
2.1 redo log 和 binlog
就将赊账小黑板和账本一样,由于修改记录需要查询账本,速度很慢,那么我们可以先在小黑板上记载修改记录,等资源空闲了再去修改账本。
当redo log写不下了,就会将一部分写到binlog里,腾出空间。
整体的运行过程如下:
redo log的prepare和commit叫做两阶段提交,用于保证在crash恢复后,redo log和binlog的数据一致性。
三、数据库索引
3.1 索引的类别
- Hash
Hash的查询效率最高,但是范围查找效率很低。
- 树
树的查询和范围查找效率都毕竟均衡,常用B+树。
3.2 主键索引和普通索引的区别
在InnoDB存储引擎中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。
从图中不难看出,根据叶子节点的内容,索引类型分为主键索引和非主键索引。
主键索引的叶子节点存的是整行数据。在InnoDB里,主键索引也被称为聚簇索引(clusteredindex)。
非主键索引的叶子节点内容是主键的值。在InnoDB里,非主键索引也被称为二级索引(secondaryindex)。
根据上面的索引结构说明,我们来讨论一个问题:基于主键索引和普通索引的查询有什么区别?
-
如果语句是
select * from T where ID=500
,即主键查询方式,则只需要搜索ID这棵B+树; -
如果语句是
select * from T where k=5
,即普通索引查询方式,则需要先搜索k索引树,得到ID的值为500,再到ID索引树搜索一次。这个过程称为
回表
。
也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。
- 因此用自增主键是一个既节省空间(int比其他字段短)又加速(新增记录而不修改记录)的方法
3.3 覆盖索引
了解了上述的回表情况,我们如何避免回表加快查询速度呢。
将
select * from T where k between 3 and 5
改为
select ID from T where k between 3 and 5
,相当于字段k的索引上已经“覆盖”了我们的查询需求,成为查询索引。
3.4 最左前缀原则
有没有可能用一个索引起到多个索引的效果?
观察上图,当我们有场景需要在字段“姓名,年龄”上进行联合查询,并且在“姓名”单字段上进行查询,那么我们通过一个“姓名,年龄”的联合索引就能起到加速作用。
如果你要查的是所有名字第一个字是“张”的人,你的SQL语句的条件是
where name like ‘张%’
。这时,你也能够用上这个索引,查找到第一个符合条件的记录是ID3,然后向后遍历,直到不满足条件为止。
可以看到,不只是索引的全部定义,只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以是联合索引的最左N个字段,也可以是字符串索引的最左M个字符。
因此,联合索引的字段顺序排列就很重要。
3.5 索引下推
刚刚说的最左前缀只利用了联合索引的第一个字段,那么我们如果还想利用第二个字段呢?
如果现在有一个需求:检索出表中“名字第一个字是张,而且年龄是10岁的所有男孩”。
select * from tuser where name like ' 张 %' and age=10 and ismale=1;
索引下推优化(indexconditionpushdown),可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
对比下图,没有索引下推和有索引下推的查询过程。(MySQL5.6之后都有索引下推)
参考:
【1】极客时间Mysql实战