MySQL优化的底层逻辑

news2024/10/7 4:23:06

文章目录

  • 前言
  • 索引的底层结构
  • 数据与索引的关系
    • 聚簇索引的数据存储
    • 普通索引的数据存储
  • 索引的命中逻辑
  • 怎么理解索引失效
  • 总结

前言

去年刚开始写博客的时候写了一篇《MySQL性能调优参考》,文章中提到优化的几个技巧,比如数据类型的使用、范式和反范式的合理使用、索引的使用及其使用的注意事项等等。其中我们接触最多的就是索引,你可能知道索引的底层结构是B+Tree、使用索引要遵守最左匹配原则,那你知道为什么要用B+Tree、为什么使用索引有那么多注意事项吗?所以还是要知其然知其所以然,看完这篇文章你就懂了。

索引的底层结构

首先,MySQL索引的存储不仅仅只有B+Tree的结构,还有Hash和全文,这个在创建索引时可以指定。

MySQL中常用的InnoDB存储引擎默认使用B+Tree结构,毕竟使用MySQL时范围查找的场景是最多的,当然如果等值查询比如热点数据这种场景可以使用Hash索引,如果有大量的文本数据需要搜索和处理,使用全文索引是一个常见的选择。这里只对B+Tree索引展开介绍,如果不了解B+Tree的可以先了解下前置知识《常见的数据结构及应用》。

数据与索引的关系

要想知道在使用索引为什么要有那么多的注意事项和原则,我们需要先了解一下数据和索引的关系。接下来我通过一个简单例子,说明一下B+Tree索引在存储数据中的具体实现。

先创建一张商品表,设置id为主键:

CREATE TABLE `goods`  (
  `id` int PRIMARY KEY NOT NULL,
  `goods_no` varchar(20)  DEFAULT NULL,
  `goods_name` varchar(255) DEFAULT NULL,
  `goods_price` decimal(10, 2) DEFAULT NULL
)

表中的数据如下:
在这里插入图片描述

聚簇索引的数据存储

在向MySQL插入一行数据时,默认情况下,会根据主键字段的数据作为索引键值构建B+Tree索引,这个过程会遵循B+Tree的规则。goods表中的这些数据在B+Tree中的逻辑结构如下图

在这里插入图片描述

可以看到在非叶子节点上只存放了主键列的值,而叶子节点存放了主键对应的整行数据,这种索引又叫「聚簇索引」 也叫「主键索引」 。当sql句为 select id from goods 或者 select * from goods where id = 1 时都会通过这个索引进行查询到数据,这个可以通过执行计划看到

在这里插入图片描述

普通索引的数据存储

而我们自行设置的其他索引都称之为「普通索引」或「二级索引」或者是「非聚簇索引」,在向MySQL插入一行数据时除了会根据主键构建一个聚簇索引,还会根据其他索引列构建对应的普通索引。这里为goods_no、goods_name列创建一个普通索引后,表中的数据在这个索引中逻辑结构如下图

在这里插入图片描述

可以看到在普通索引中每个非叶子节点的键值存放的是索引列的数据,而叶子节点不仅存放了索引列的数据,还存放了对应的主键值。

索引的命中逻辑

那么,问:那么请问,当执行以下sql时会使用哪个索引?为什么?

sql1:select id,goods_name from goods where goods_no='00001'
sql2:select id,goods_name,goods_price from goods where goods_no='00001'
sql3:select id,goods_name,goods_price from goods where goods_name='goods1'

sql1中使用了goods_no、goods_name创建的普通索引。因为查询的字段idgoods_name都在这个索引的叶子节点中,可以直接返回这些数据,所以不用再去其他地方查询,这个过程也叫做「覆盖索引」,执行计划中的Using index 就可以说明。

在这里插入图片描述

sql2中使用了普通索引和主键索引。因为要查询的goods_price在普通索引没有找到,所以在拿到主键后会去主键索引中再查找一次,这个过程叫做「回表」,也就是说要查两个 B+Tree 才能查到数据(如下图)。通常情况下要尽量避免回表操作,因为多一次扫描查询效率就会下降一些。

在这里插入图片描述

sql3没有使用索引,走的是全表扫描。首先条件字段并未使用到普通索引,因为不符合「最左匹配原则」。其次查询字段id,goods_name,goods_price在两个索引中都无法匹配,因此走了全表扫描,这种现象也叫「索引失效」。

怎么理解索引失效

不论是WHERE条件也好,查询字段也罢,是否使用索引或者使用哪个索引都是「优化器」来决定的,以下几个是优化器工作时索引失效的例子及说明:

  1. 当索引列的唯一值与总行数的区分度很小,比如索引列的值就是男和女,那么优化器就会忽略索引直接全表扫描,因为这种情况下即使通过索引定位数据,也会因为索引列的重复去访问大部分的数据页,加上维护索引以及访问索引的开销,这样下来还不如直接去访问数据页。
  2. 当优化器看到WHERE条件中有OR关键字时,会看前后两个字段是否都是索引列,因为OR的含义就是两个只要满足一个即可,所以只要有一个不是索引列就会进行全表扫描。
  3. 说一下sql3的「最左匹配原则」,当构建联合索引(goods_no,goods_name)时,会先对goods_no进行排序插入,如果遇到goods_no相同时再对goods_name进行排序插入,所以优化器在看到查询字段goods_name与索引字段顺序不一样时就会忽视掉这个索引,从而导致索引失效。如果符合最左匹配原则,在根据索引查找数据时会先根据goods_no进行比较,在goods_no相同时再根据goods_name进行比较。
  4. 还有大家都知道的索引列使用函数、表达式会失效,为什么?因为B+Tree中的节点存放的是列的原始数据,你拿一个经过函数或者表达式计算的值来查找当然不认识了。
    5 还有等等索引失效场景。

总结

所以我们不需要背索引失效场景以及索引使用的注意事项,只要知道数据在B+Tree索引中是怎样存储的、优化器是怎么选择索引的,这些那些的原则、注意事项还需要背吗?还是那句话,知其然知其所以然。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1221439.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安装部署Esxi7.0并创建虚拟机

1. Esxi介绍 ESXI虚拟平台是VMware出品的一个强大平台,它可以直接安装在物理机上,从而充分利用物理奖性能,虚拟多个系统出来。ESXI是一个带WEB管理后台的软件,非常适合安装在服务器上,然后直接通过网页进行远程管理。…

测试开发环境下centos7.9下安装docker的minio

按照以下方法进行 1、安装docker,要是生产等还是要按照docker-ce yum install docker 2、启动docker service docker start 3、 查看docker信息 docker info 4、加到启动里 systemctl enable docker.service 5、开始docker pull minio/minio 但报错&#x…

TP-LINK联洲面试题

文章目录 1.说一下微服务架构?2.微服务优缺点3.负载均衡的实现算法4.Redis集群部署方式?5.MySQL主从复制?5.1 配置流程5.2 优缺点分析6.口头手撕快排7.队列实现栈和栈实现队列7.1 队列实现栈7.2 栈实现队列8.进程有几种状态?9.Spring Boot Actuator?10.外键、主键和索引?…

ImportError: cannot import name ‘url_quote‘ from...

👨🏻‍💻 热爱摄影的程序员 👨🏻‍🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻‍🏫 一位高冷无情的编码爱好者 大家好,我是全栈工…

Netty传输object并解决粘包拆包问题

⭐️ 前言 大家好,笔者之前写过一篇文章,《Netty中粘包拆包问题解决探讨》,就Netty粘包拆包问题及其解决方案进行了探讨,本文算是这篇博客的延续。探讨netty传输object的问题。 本文将netty结合java序列化来传输object并解决粘包…

C语言——求1/1-1/2+1/3-......+1/99-1/100的值

#include<stdio.h> int main() {int i 1;double sum 0;int flage 1;for(i 1;i < 100; i){sumflage*1.0/i;flage -flage; //正负号}printf("%lf\n",sum);return 0; }

2024年山东省职业院校技能大赛中职组“网络安全”赛项竞赛试题-B

2024年山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题-B 一、竞赛时间 总计&#xff1a;360分钟 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 A、B模块 A-1 登录安全加固 180分钟 200分 A-2 本地安全策略设置 A-3 流量完整性保护 A-4 …

二十一、数组(1)

本章概要 数组特性 用于显示数组的实用程序 一等对象返回数组 简单来看&#xff0c;数组需要你去创建和初始化&#xff0c;你可以通过下标对数组元素进行访问&#xff0c;数组的大小不会改变。大多数时候你只需要知道这些&#xff0c;但有时候你必须在数组上进行更复杂的操作…

Ubuntu18.04安装Moveit框架

简介 Moveit是一个由一系列移动操作的功能包组成的集成化开发平台,提供友好的GUI,是目前ROS社区中使用度排名前三的功能包,Moveit包含以下三大核心功能,并集成了大量的优秀算法接口: 运动学:KDL,Trac-IK,IKFast...路径规划:OMPL,CHMOP,SBPL..碰撞检测:FCL,PCD... 一、更新功…

前段-用面向对象的方式开发一个水管小鸟的游戏

首先准备好各类空文件 index.js css html 和图片 图片是下面这些&#xff0c;如果没有的可在这里下载 2 开发开始 好了&#xff0c;基础准备工作完毕&#xff0c;开发开始&#xff0c; 首先&#xff0c;先把天空&#xff0c;大地&#xff0c;小鸟的盒子准备好&#xff0c;并…

基于探路者算法优化概率神经网络PNN的分类预测 - 附代码

基于探路者算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于探路者算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于探路者优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…

main函数的数组参数是干嘛用的

今天在看项目代码的时候&#xff0c;突然看到项目中用到了main函数的参数args&#xff0c;在这之前我还没怎么注意过这个参数&#xff0c;一时间居然不知道这个参数是干嘛的&#xff01; 虽然也写过一些java和scala&#xff0c;但是确实没遇到过会用这个参数的情况。 网上就查…

【PIE-Engine 数据资源】中国叶面积指数(LAI)月度合成产品

文章目录 一、 简介二、描述三、波段四、示例代码运行结果参考资料 一、 简介 数据名称中国叶面积指数&#xff08;LAI&#xff09;月度合成产品时间范围2002-2021年空间范围全国数据来源航天宏图代码片段var images pie.ImageCollection(“EMDO/MODIS_MONTH_LAI_CHINA”) 二…

Arduino项目式编程教学前言

前言–先聊聊我的经历 在停更数年之后&#xff0c;还是打算重新开启Arduino编程教学这一项目&#xff1b;这几年间&#xff0c;我从Arduino编程开发教学&#xff0c;转到C及python教学&#xff0c;又到如今的高中数学教学&#xff0c;跨度竟如此之大&#xff0c;但始终未脱离教…

echarts 三角锥形柱状图 + 带阴影的折线图示例

该示例有如下几个特点&#xff1a; ①三角锥形折线图 ②折线图自带阴影 ③三角锥形鼠标放置时颜色改变 ④数据随着鼠标移动而展示 ⑤鼠标放置时tooltip样式自定义&#xff08;echarts 实现tooltip提示框样式自定义-CSDN博客&#xff09; 代码如下&#xff1a; this.options …

【GUI】-- 08 JButton、JRadioButton、JCheckBox

GUI编程 03 Swing 3.5 JButton 图片置于按钮之上的JButton&#xff1a; package com.duo.lesson05;import javax.swing.*; import java.awt.*; import java.net.URL;public class JButtonDemo01 extends JFrame {public JButtonDemo01() {Container contentPane getConten…

opencv(4):颜色空间

文章目录 颜色空间RGB 人眼的色彩空间HSV 色彩空间HSLYUVYUV420&#xff1a;YUV422&#xff1a;YUV444&#xff1a; 颜色空间转换代码示例 颜色空间 不同色彩空间显示效果是不一样的。 RGB 人眼的色彩空间 HSV 色彩空间 HSV 代表色相&#xff08;Hue&#xff09;、饱和度&a…

YOLO改进系列之注意力机制(EffectiveSE模型介绍)

模型结构 ESE(Effective Squeeze and Extraction) layer是CenterMask模型中的一个block&#xff0c;基于SE&#xff08;Squeeze and Extraction&#xff09;改进得到。与SE的区别在于&#xff0c;ESE block只有一个fc层&#xff0c;(CenterMask : Real-Time Anchor-Free Insta…

2019年12月 Scratch(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 以下程序执行后,角色面向的方向是? A:右上 B:右下 C:左上 D:左下 答案:B 面向-135度,是面向左下角,向右旋转-90度等于向左旋转90度。所以会旋转到右下角。 第2题 以下程…

WordPress网站迁移实战经验

前几日,网站服务器到期,换了服务商,就把我的WordPress的网站迁移到本地电脑了。方便以后文章迁移。 本次迁移网站主要经历以下几个步骤。 1.域名转出。 2.备份数据库及网站文件下载。 3.重新搭建WordPress网站。 4.网站文件及数据库导入。 下面详细介绍下每个步骤的操作…