Mysql数据库

本文详细介绍了InnoDB存储引擎的数据页结构,包括Infimum和Supremum记录,以及页目录在快速搜索中的作用。讨论了B+树作为索引的优势,解释了为何在某些场景下选择B+树而非B树或跳表。此外,还探讨了索引失效的情况以及SQL查询优化的方法,如减少数据扫描、返回更少数据和降低CPU开销。
摘要由CSDN通过智能技术生成

 行格式

Mysql一条记录实际上是分两部分存储的: 

 

重点需要知道在 记录的额外信息 中有一个两字节的称为 next_record 指针,通过该指针各条记录可以组成一个单向链表: 

单向链表中的记录的主键值是按照从小到大的顺序排序的,也就是说这个单向链表是有序的。 

## Innodb数据页结构

InnoDB是以页为单位从磁盘上加载数据的。页面可以配置成 4KB、8KB、16KB、32KB、64KB几种大小,不过默认是16KB的。 

 

下边假设某个页中存储了16条用户插入的记录,该数据页的效果图如下所示: 

其中 `Infimum记录` 和 `Supremum记录` 是InnoDB给我们自动生成的两个伪记录,并且规定: 

`Infimum记录` 作为本页面中最小的记录 

`Supremum记录` 作为本页面中最大的记录 

为了解决快速搜索的问题,设计InnoDB的大叔引入了一个称作 页目录 的东西。具体的做法就是将单向链表中的记录分成若干个组

然后将把每个组最大的那条记录在页面中的地址(就是距离页面第0个字节处的偏移量)取出来单 

独放到页面中的一个部分。每个地址占用2个字节,多个地址就可以组成一个数组结构,如下图所 

示:

 

可见, `页目录` 本质上就是一个指针数组,指针指向的记录是有序的,我们就可以针对这 

个 `页目录` 进行二分搜索。比方说我们想找主键值为6的记录,那就可以通过页目录先进行二分查 

找,定位到主键值6其实是在第3组里,然后再遍历第3组中的记录,就可以定位到具体的主键值6 

的记录在哪里了。 

索引用的什么数据结构,为什么选B+不用B为什么不用跳表

B+树非叶子节点不会存储所有节点,层数低

B+树叶子结点有双向链表,可以遍历

b+树是在平衡树的基础上做了矮胖化处理,降低了树高,将一部分随机io转化为顺序io,扫的数据很多,时间复杂度其实是变大了,但是因为磁盘顺序io比随机io快太多了,所以可以牺牲一点时间复杂度来提高性能,但是redis都是在内存里面,不存在随机io和顺序io的区别,也就只需要考虑时空复杂度,用跳表肯定更好,同时跳表的实现相对来说简单一点

什么情况下索引失效

最佳左前缀法则 严禁左模糊或者全模糊 %*%

列 带了表达式

类型转换导致索引失效 123 ‘123’

慢SQL分析与优化

优化方式

SQL 语句执行效率的主要因素

  • 数据量
    • SQL 执行后返回给客户端的数据量的大小;
    • 数据量越大需要扫描的 I/O 次数越多,数据库服务器的 IO 更容易成为瓶颈。
  • 取数据的方式
    • 数据在缓存中还是在磁盘上;
    • 是否能够通过全局索引快速寻址;
    • 是否结合谓词条件命中全局索引加速扫描。
  • 数据加工的方式
    • 排序、子查询、聚合、关联等,一般需要先把数据取到临时表中,再对数据进行加工;
    • 对于数据量比较多的计算,会消耗大量计算节点的 CPU 资源,让数据加工变得更加缓慢;
    • 是否选择了合适的 join 方式

优化思路

  • 减少数据扫描(减少磁盘访问)
    • 尽量在查询中加入一些可以提前过滤数据的谓词条件,比如按照时间过滤数据等,可以减少数据的扫描量,对查询更友好;
    • 在扫描大表数据时是否可以命中索引,减少回表代价,避免全表扫描。
  • 返回更少数据(减少网络传输或磁盘访问)
  • 减少交互次数(减少网络传输)
    • 将数据存放在更快的地方
    • 某条查询涉及到大表,无法进一步优化,如果返回的数据量不大且变化频率不高但访问频率很高,此时应该考虑将返回的数据放在应用端的缓存当中或者 Redis 这样的缓存当中,以提高存取速度。
  • 减少服务器 CPU 开销(减少 CPU 及内存开销)
  • 避免大事务操作
  • 利用更多资源(增加资源)

    优化案例

    数据分页优化

    select * from table_demo where type = ? limit ?,?;

    优化方式一:偏移 id

    lastId = 0 or min(id)
    do {
    select * from table_demo where type = ? and id > {#lastId}  limit ?;
    lastId = max(id)
    }while (isNotEmpty)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值