MySQL - 聚簇索引和非聚簇索引,回表查询,索引覆盖,索引下推,最左匹配原则

news2024/11/26 22:51:14

聚簇索引和非聚簇索引

聚簇索引和非聚簇索引是 InnoDB 里面的叫法

一张表它一定有聚簇索引,一张表只有一个聚簇索引在物理上也是连续存储的

它产生的过程如下:

  1. 表中有无有主键索引,如果有,则使用主键索引作为聚簇索引;
  2. 如果没有主键索引,则看表中有无唯一索引,那么使用第一个唯一索引;
  3. 如果以上两个条件都不满足,InnoDB 则会生成隐藏聚簇索引。

聚簇索引

聚簇索引一般是主键索引,

例如主键索引 id 对应的聚簇索引结构图(叶子节点存储整表数据):

 

非聚簇索引

非聚簇索引在 InnoDB 也叫做二级索引,非聚簇索引是普通列的索引(非主键索引)

例如普通 class_id 对应的非聚簇索引结构图(叶子节点存储的是聚簇索引):

 

MySQL的InnoDB索引数据结构是B+树

聚簇索引叶子结点存储的是行数据,而非聚簇索引叶子节点存储的是聚簇索引,因此通过聚簇索引可以找到真正的行数据;
由于非聚簇索引的叶子结点存储的是聚簇索引,因此使用非聚簇索引还需要进行回表查询,所以在查询效率方面,聚簇索引要高于非聚簇索引;
聚簇索引一般为主键索引,而一个表中只能有一个主键,因此一个表中也只能有一个聚簇索引,而非聚簇索引则没有数量上的限制。


 什么是回表查询 

由于非聚簇索引的叶子节点存储的不是真正的数据,而是聚簇索引,所以在使用普通索引进行查询操作时,会先查询到聚簇索引,然后再去聚簇索引对应的 B+ 数去查询真正的数据,这个过程就叫做回表查询。


例子

下面我们创建了一个学生表,做三种查询,来说明什么情况下是聚簇索引,什么情况下不是。

create table student (
    id bigint,
    no varchar(20) ,
    name varchar(20) ,
    address varchar(20) ,
    PRIMARY KEY (`branch_id`) USING BTREE,
    UNIQUE KEY `idx_no` (`no`) USING BTREE
)ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

第一种,直接根据主键查询获取所有字段数据,此时主键是聚簇索引,因为主键对应的索引叶子节点存储了id=1的所有字段的值。

select * from student where id = 1

第二种,根据编号查询编号和名称,编号本身是一个唯一索引,但查询的列包含了学生编号和学生名称,当命中编号索引时,该索引的节点的数据存储的是主键ID,需要根据主键ID重新查询一次,所以这种查询下no不是聚簇索引

select no,name from student where no = 'test'

第三种,我们根据编号查询编号(有人会问知道编号了还要查询?要,你可能需要验证该编号在数据库中是否存在),这种查询命中编号索引时,直接返回编号,因为所需要的数据就是该索引,不需要回表查询,这种场景下no是索引覆盖 

select no from student where no = 'test'

主键一定是聚簇索引,MySQL的InnoDB中一定有主键,即便研发人员不手动设置,则会使用unique索引,没有unique索引,则会使用数据库内部的一个行的id来当作主键索引,其它普通索引需要区分SQL场景,当SQL查询的列就是索引本身时,我们称这种场景下该普通索引也可以叫做聚簇索引,MyisAM引擎没有聚簇索引。


什么是索引覆盖

        索引覆盖是指在一个查询语句中,某个索引已经 "覆盖了" 需要被查询出来的列,此时就不需要进行回表查询了,这就叫做索引覆盖!!(索引覆盖它是非聚簇索引中的一个特殊情况)

当我们写了这样一个 SQL,实际上它走的是辅助索引,结构如下图:

select id from student where name = 'Bob';

  1. 辅助索引(非聚簇索引)中的查询,一般是需要查询两次,第一次查询出聚簇索引,然后根据聚簇索引回表查询,最终拿到行数据。
  2. 但是此处我的查询需求刚好就是聚簇索引,因此一次查询就可以拿到需要的列,不需要进行回表,这就是索引覆盖~

 以下四种情况都属于索引覆盖 >>

// 联合索引 (name,age)
select name from student where.....
 
select age from student where.....
 
select name,age from student where.....
 
select address,name,age from student where address = '深圳';

最后一个 SQL 因为 where 条件后面可以知道 address,所以也不需要回表查询!!


索引下推

索引下推是指在查询非聚簇索时,拿到了叶子结点的聚簇索引,然后对聚簇索引中包含的字段先做判断,直接过滤掉不满足条件的记录,从而减少回表次数,这就是索引下推!!(索引下推是在 MySQL 5.6 之后才引入的,它属于非聚簇索引中功能)

以 user 表中的联合索引(name,age)为例:

select * from user where name='张%' and age='10';
 
// 表中有四条数据
// 1  张三  10
// 2  张四  11
// 3  张五  12
// 4  老六  13

MySQL 5.6 之前没有索引下推,它的执行流程如下:

① 在非聚簇索引中根据 name='张%' 查到聚簇索引中匹配的 id

② 使用匹配的 id 进行回表查询

 此时会进行三次回表操作,而联合索引中的 age 字段就没用上。

MySQl 5.6 之后引入索引下推,它会根据 name='张%' 和 age 一起过滤数据:

【好处】:它的第二步操作就可以节省回表的次数

② 使用匹配的 id 进行回表查询

 引入索引下推后,只执行了一次回表查询,这就是索引下推的好处。


什么是最左匹配原则

  • 最左匹配原则是指索引以最左边的为起点,任何连续的索引都能匹配上,
  • 当遇到范围查询 (>、<、between、like) 就会停止匹配。

比如联合索引 index(a,b,c),以下 SQL 来理解什么是最左匹配原则:

select * from user where a=1; // 只使用索引 a
 
select * from user where b=2; // 不使用索引
 
select * from user where c=3; // 不使用索引
 
select * from user where a=1 and b=2; // 只使用索引 a,b
 
select * from user where a=1 and c=3; // 只是用索引 a
 
select * from user where b=2 and c=3; // 不使用索引
 
select * from user where a=1 and b=2 and c=3; // 使用索引 a,b,c
 
select * from user where a=1 and b like '%xxx' and c=3; // 只使用索引 a,b

【疑惑一】

        不是说使用了 like,就停止匹配了吗,为什么前面的索引下推使用了 name='张%' 还能再拿 age 进行过滤呢 ?

对于 like 查询,它的常见写法有三种:

模糊匹配后面任意字符:like '张%'
模糊匹配前面任意字符:like '%张'
模糊匹配前后任意字符:like '%张%'
        这三种情况,只有第一种情况是会走索引的,其他的都会导致索引失效,所以前面索引下推例子中的 name='张%' 是不会停止匹配的~

【疑惑二】

        当我们写出这样的条件语句 where a=1 and c=3 and b=2 时,引擎为什么不把它调整为 a,b,c 的顺序呢?

        MySQL 8.0 之后才涉及到这样的调优,但是具体会不会调优,是不一定的,因为索引调优的主动权在索引的优化器里面的,而优化器这个东西,它很玄学,所以不知道它会不会进行调优。

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

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

相关文章

Kafka 最佳实践:构建可靠、高性能的分布式消息系统

Apache Kafka 是一个强大的分布式消息系统&#xff0c;被广泛应用于实时数据流处理和事件驱动架构。为了充分发挥 Kafka 的优势&#xff0c;需要遵循一些最佳实践&#xff0c;确保系统在高负载下稳定运行&#xff0c;数据可靠传递。本文将深入探讨 Kafka 的一些最佳实践&#x…

TailwindCSS 配置可视化检查器

问题 TailwindCSS 框架为我们提供了大量默认的类和属性&#xff0c;而且开发者也能够自定义类和配置。 对于初学者来说&#xff0c;这些配置其实是比较复杂的&#xff0c;这也是tailwindcss最大的入手成本&#xff0c;开发者的记忆负担和心智负担也都比较大。 有没有办法能够…

【BUG】微信小程序image不会随着url动态变化

问题描述&#xff1a; 第一次打开界面&#xff0c;显示的是默认头像而不是用户头像&#xff0c;似乎image里面的src只要第一次有值就不会再更新了 解决 不要给src里面的变量设置初始值&#xff0c;而是直接赋空值

ChatGPT 应用开发(一)ChatGPT OpenAI API 免代理调用方式(通过 Cloudflare 的 AI Gateway)

前言 开发 ChatGPT 应用&#xff0c;我觉得最前置的点就是能使用 ChatGPT API 接口。首先我自己要能成功访问&#xff0c;这没问题&#xff0c;会魔法就可以本地调用。 那用户如何调用到我的应用 API 呢&#xff0c;我的理解是通过用户能访问到的中转服务器向 OpenAI 发起访问…

[软件工具]文本去重含有重复的全部删除不是保留一个重复的方法

文本去重含有重复的全部删除不是保留一个重复的方法 第一步&#xff1a;首先打开软件 第二步&#xff1a;设置好保存目录后&#xff0c;将文件夹拖拽到列表&#xff0c;软件会自动识别导入txt 第三步&#xff1a;点击开始处理&#xff0c;即可完成任务 本软件支持批量处理&a…

Go1.21.0 程序启动过程

版本说明 Go 1.21.0操作系统&#xff1a;Windows11 Intel64 结论先行 开发关注版 在 Go 语言中&#xff0c;启动顺序通常如下&#xff1a; 导入包&#xff1a;首先&#xff0c;Go 编译器按照源文件中的 import 语句导入所有需要的包。初始化常量和变量&#xff1a;接着&am…

uc_16_UDP协议_HTTP协议

1 UDP协议 适合游戏、视频等情景&#xff0c;安全性要求不高&#xff0c;效率要求高。 1&#xff09;UDP不提供客户机与服务器的链接&#xff1a; UDP的客户机与服务器不必存在长期关系。一个UDP的客户机在通过一个套接字向一个UDP服务器发送了一个数据报之后&#xff0c;马上…

UE小:物品拼装功能

蓝图B1的实现步骤&#xff1a; 获取玩家控制器和视角&#xff1a;首先获取玩家控制器&#xff0c;然后使用Deproject Screen to World节点将屏幕上的鼠标位置转换为世界空间中的一条射线。 射线检测&#xff1a;使用Line Trace by Channel或Line Trace for Objects节点发射射线…

【数学建模】《实战数学建模:例题与讲解》第十讲-时间序列预测(含Matlab代码)

【数学建模】《实战数学建模&#xff1a;例题与讲解》第十讲-时间序列预测&#xff08;含Matlab代码&#xff09; 基本概念移动平均&#xff08;Moving Average, MA&#xff09;:指数平滑法&#xff08;Exponential Smoothing&#xff09;:季节性调整&#xff08;Seasonal Adju…

并发编程的基本概念

进程与线程 进程 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至 CPU&#xff0c;数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的当一个程序被运行&…

【电路笔记】-压敏电阻

压敏电阻 文章目录 压敏电阻1、概述2、交流波形瞬变3、抗静电能力4、特性曲线5、压敏电阻电容值6、金属氧化物压敏电阻7、压敏电阻应用8、总结 压敏电阻是一种无源两端固态半导体器件&#xff0c;用于为电气和电子电路提供保护。 1、概述 与提供过电流保护的保险丝或断路器不同…

linux 14网站架构 编译安装mysql数据库

目录 LNMP网站架构下载源码包mysql 下载位置 mysql 安装1.1、清理安装环境&#xff1a;1.2、创建mysql用户1.3、从官网下载tar包1.4、安装编译工具1.5、解压1.6、编译安装编译安装三部曲1.7、初始化初始化,只需要初始化一次1.8、启动mysql1.9、登录mysql1.10、systemctl启动方式…

【Hive】启动beeline连接hive报错解决

1、解决报错2、在datagrip上连接hive 1、解决报错 刚开始一直报错&#xff1a;启动不起来 hive-site.xml需要配置hiveserver2相关的 在hive-site.xml文件中添加如下配置信息 <!-- 指定hiveserver2连接的host --> <property><name>hive.server2.thrift.bin…

YOLOV3 SPP 目标检测项目(针对xml或者yolo标注的自定义数据集)

1. 目标检测的两种标注形式 项目下载地址:YOLOV3 SPP网络对自定义数据集的目标检测(标注方式包括xml或者yolo格式) 目标检测边界框的表现形式有两种: YOLO(txt) : 第一个为类别,后面四个为边界框,x,y中心点坐标以及h,w的相对值 xml文件:类似于网页的标注文件,里面会…

算法通关村第十八关-白银挑战回溯热门问题

大家好我是苏麟 , 今天带来几道小题 . 回溯主要解决一些暴力枚举也搞不定的问题&#xff0c;例如组合、分割、子集、排列&#xff0c;棋盘等。这一关我们就看几个例子 大纲 回溯热身-再论二叉树路径问题二叉树的所有路径路径总和 II 回溯热门问题组合总和问题组合总和 子集问题…

Android12之解决:scripts/gcc-wrapper.py, line 79, in run_gcc(一百六十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

机器学习基本概念2

资料来源&#xff1a; https://www.youtube.com/watch?vYe018rCVvOo&listPLJV_el3uVTsMhtt7_Y6sgTHGHp1Vb2P2J&index1 https://www.youtube.com/watch?vbHcJCp2Fyxs&listPLJV_el3uVTsMhtt7_Y6sgTHGHp1Vb2P2J&index2 分三步 1、 定义function b和w是需要透…

neuq-acm预备队训练week 9 P3367 【模板】并查集

题目描述 如题&#xff0c;现在有一个并查集&#xff0c;你需要完成合并和查询操作。 输入格式 解题思路 并查集的用法 AC代码 #include <bits/stdc.h> using namespace std; #define Max 1000001 int zi,xi[Max],yi[Max],Fa[Max]; int find(int x); bool qu(int u,…

MIT线性代数笔记-第28讲-正定矩阵,最小值

目录 28.正定矩阵&#xff0c;最小值打赏 28.正定矩阵&#xff0c;最小值 首先正定矩阵是一个实对称矩阵 由第 26 26 26讲的末尾可知正定矩阵有以下四种判定条件&#xff1a; 所有特征值都为正左上角所有 k k k阶子矩阵行列式都为正&#xff08; 1 ≤ k ≤ n 1 \le k \le n …

transformer模型结构|李宏毅机器学习21年

来源&#xff1a;https://www.bilibili.com/video/BV1Bb4y1L7FT?p4&vd_sourcef66cebc7ed6819c67fca9b4fa3785d39 文章目录 概述seq2seqtransformerEncoderDecoderAutoregressive&#xff08;AT&#xff09;self-attention与masked-self attentionmodel如何决定输出的长度…