MySQL 索引原理以及 SQL 优化

news2024/9/21 20:43:44

索引

  • 索引:一种有序的存储结构,按照单个或者多个列的值进行排序。
  • 索引的目的:提升搜索效率。
  • 索引分类:
    • 数据结构
      • B+ 树索引(映射的是磁盘数据)
      • hash 索引(快速锁定内存数据)
      • 全文索引
        • 将存储在数据库中的整本书和整篇文章中的任意内容信息查找出来的技术。
        • 在短字符串中用 LIKE %;在全文索引中用 match 和 against。
        • 一般使用 elasticsearch。
    • 物理存储
      • 聚集索引(聚簇索引):主键所对应的 B+ 树。(包含主键 ID 和表数据)
      • 辅助索引(二级索引):除了主键之外的其它索引。(只包含 key 和主键 ID)
        • 回表查询:辅助索引 B+ 树通过 key 查找到主键 ID,然后通过主键 ID 查找聚簇索引 B+ 树从而得到表记录。
      struct zcoder_tb {
      	int id;       // primary key
      	string name;  // key
      	string phone; // key
          short age;
      }; 
      
      map<int, zcoder_tb> // 聚簇索引
      map<string, int>    // 辅助索引
      map<string, int>    // 辅助索引
      
    • 列属性
      • 主键索引:非空唯一索引,一个表只有一个主键索引;在 innodb 中,主键索引的 B+ 树包含表数据信息
        PRIMARY KEY(key1, key2)
        
      • 唯一索引:不可以出现相同的值,可以有 NULL 值。
        UNIQUE(key1, key2)
        
      • 普通索引:允许出现相同的索引内容 。
        INDEX(key1, key2)
        -- OR
        KEY(key1, key2)
        
      • 前缀索引:只比较长字符串的前几个字符。
    • 列的个数
      • 单列索引
      • 组合索引:对表上的多个列进行索引。
        INDEX(key1, key2)
        UNIQUE(key1, key2)
        PRIMARY KEY(key1, key2)
        
  • 索引代价
    • 占用空间(有多个索引,就有多个 B+ 树)。
    • 维护的代价:DML 操作变慢(如果修改的字段有索引(非聚簇索引),除了要修改聚簇索引 B+ 树,还要修改对应的辅助索引 B+ 树)。
  • 索引的使用场景
    • where
    • group by
    • order by
  • 不使用索引的场景
    • 不使用 where / / /group by / / /order by
    • 列中的数据区分度不高
    • 经常修改的列
    • 表数据量少
  • innodb 中 B+ 树(多路平衡搜索树)
    在这里插入图片描述
    • 特征:
      • 非叶子节点只存储索引信息(只存储 key)。
      • 叶子节点还存储数据信息(存储 key 和 value)。
      • 叶子节点之间依次相连。
      • 节点的大小为 16 KB,映射的是连续的磁盘页(通过 mmap 映射磁盘数据)。
      • 一个叶子节点至少存储两行数据,如果某一行数据大于 16 KB,则会截取一部分数据进行存储,并保留一个地址位(记录另一个 B+ 树所对应的地址),然后把剩余的数据存储在另一个 B+ 树中。
    • 为什么采用 “多路” 的树结构
      • 一个节点多条链路,相较于平衡二叉搜索树是一个更加矮胖的结构,树的高度较低,较少的磁盘 IO 次数来索引数据。
    • 为什么非叶子节点只存储索引信息
      • B+ 树节点映射固定大小的磁盘数据,可以包含更多的索引信息,能快速锁定数据所在叶子节点的位置。
    • 为什么叶子节点依次相连
      • 便于范围查询,避免中序遍历回溯去查找下一个节点。
    • 索引信息和数据信息的分层管理,便于高效地组织磁盘数据,快速实现单点和范围查询。
  • 聚簇索引查找流程
select * from user where id >= 18 and id < 40;

在这里插入图片描述

  • 辅助索引查找流程
    • 辅助索引的叶子节点不包含行记录的全部数据,只存储了用来排序的 key 和一个 bookmark,该书签存储了聚集索引的 key。
-- 某个表 包含 id、name、lockyNum; id是主键,lockyNum 是辅助索引;
select * from user where lockyNum = 33;

在这里插入图片描述

  • innodb 体系结构
    在这里插入图片描述
    在这里插入图片描述
    • Buffer Pool
      • 缓存表和索引数据( 聚簇索引 B+ 树的数据)。
      • 采用 LRU 算法,只缓存比较热的数据。
      • 缓存大小为 128 MB。
      • 有三个链表组织数据
        • free list 组织 Buffer Pool 中未使用的缓存页。
        • flush list 组织 Buffer Pool 中的脏页,也就是待刷磁盘的页。
        • lru list 组织 Buffer Pool 中的冷热数据,当 Buffer Pool 没有空闲页时,将把 lru list 中最久未使用的数据淘汰。
      • Buffer Pool 中的数据修改没有刷到磁盘,怎么确保内存中数据安全(mysql 关闭时,内存数据丢失)?
        在这里插入图片描述
    • Change Buffer
      • Change Buffer 缓存辅助索引的数据变更(DML 操作),Change Buffer 中的数据将会异步 merge 到 Buffer Pool 中。

索引存储

  • innodb 由段、区、页组成,段分为数据段、索引段、回滚段等。区大小为 1 MB(一个区由 64 个连续页构成),页的默认值为 16 KB,页为逻辑页,磁盘物理页大小一般为 4KB 或者 8KB。
  • 为了保证区中的页连续,存储引擎一般一次从磁盘中申请 4~5 个区。
  • 顺序内存 IO(数组) > > >> >> 随机内存 IO(红黑树) ≈ \approx 顺序磁盘 IO > > >> >> 随机磁盘 IO
    在这里插入图片描述

索引覆盖

  • 一种数据查询方式。
  • 针对的是辅助索引。
  • 直接通过辅助索引 B+ 树就能获取要查询的值,而无需通过回表查询。
  • 在 select 中尽量写我们所需要的字段。

最左匹配规则

  • 针对组合索引。
  • 从左到右依次匹配,遇到 > 、 < 、 b e t w e e n 、 l i k e >、<、between、like ><betweenlike 就停止匹配。
  • 尽量扩展索引,而不是单独创建索引。

索引下推

  • 目的:减少回表次数,减少 server 层和存储引擎层的交互次数,从而提升查询效率。
  • 对象:辅助索引(普通索引和联合索引场景居多)。
  • 5.6 版本后支持。
  • 没有索引下推机制:server 层向存储引擎层请求数据,在 server 层根据索引条件进行数据过滤。
  • 有索引下推:将索引条件判断下推到存储引擎中过滤数据,最终由存储引擎进行数据汇总返回给 server 层。

索引失效

  • where
    • or 或 and,包含非索引字段。
    • in 子查询。
  • LIKE 模糊查询,通配符 % 开头。
    explain select * from zcoder_tb where name like '%张';
    
  • 索引字段参与运算。
    from_unixtime(idx) = '2024-02-21'; # 索引失效
    idx = unix_timestamp("2024-02-21") # 索引有效
    
  • 索引字段发生隐式转换。
    • 将列隐式转换为某个类型,实际等价于在索引列上作用了隐式转换函数。
  • 在索引字段上使用 NOT、<> 、!= 。
    id <> 0;            # 索引失效
    idx > 0 or idx < 0; # 索引有效
    
  • 组合索引中,没有使用第一列索引。

索引原则

  • 查询频次较高且数据量大的表建立索引,索引选择使用频次较高,过滤效果好的列或者组合。
  • 使用短索引,节点包含的信息多,较少磁盘 IO 操作。比如: smallint,tinyint。
  • 对于组合索引,考虑最左侧匹配原则和索引覆盖。
  • 尽量选择区分度高的列作为索引,该列的值相同的越少越好。
  • 尽量扩展索引,在现有索引的基础上,添加复合索引,最多 6 个索引。
  • 不要 select *,尽量只列出需要的列字段,方便使用索引覆盖。
  • 索引列,列尽量设置为非空。
  • 对于很长的动态字符串,考虑使用前缀索引。 注意:前缀索引不能做 order by 和 group by。
    有时候需要索引很长的字符串,这会让索引变的大且慢。
    通常情况下可以使用某个列开始的部分字符串作为索引,这样大大的节约索引空间,从而提高索引效率。
    但这会降低索引的区分度,索引的区分度是指不重复的索引值和数据表记录总数的比值。
    索引的区分度越高则查询效率越高,因为区分度更高的索引可以让 MySQL 在查找的时候过滤掉更多的行。
    对于 BLOB , TEXT , VARCHAR 类型的列,必要时使用前缀索引。
    因为 MySQL 不允许索引这些列的完整长度,使用该方法的诀窍在于要选择足够长的前缀以保证较高的区分度。
    
    select count(distinct left(name,3))/count(*) as sel3, 
           count(distinct left(name,4))/count(*) as sel4, 
           count(distinct left(name,5))/count(*) as sel5, 
           count(distinct left(name,6))/count(*) as sel6, 
           from user;
    alter table user add key(name(4));
    
  • 可选:开启自适应 hash 索引或者调整 Change Buffer。
    select @@innodb_adaptive_hash_index;
    set global innodb_adaptive_hash_index=1; -- 默认是开启的
    
    select @@innodb_change_buffer_max_size; -- 默认值为 25,表示最多使用 1/4 的缓冲池内存空间,最大值为 50
    set global innodb_change_buffer_max_size=30

出现了 SQL 比较慢,如何解决?

  1. 找到 SQL 语句
    • show processlist
      show processlist:查看连接线程,可以查看此时线上运行的 SQL 语句。
      如果要查看完整的 SQL 语句:SHOW FULL PROCESSLIST, 然后优化该语句。
      
    • 开启慢日志查询
      -- 查看
      SHOW GLOBAL VARIABLES LIKE 'slow_query%';
      SHOW GLOBAL VARIABLES LIKE 'long_query%';
      -- 设置
      SET GLOBAL slow_query_log = ON;  -- on 开启,off 关闭
      SET GLOBAL long_query_time = 4;  -- 单位秒;默认 10s;此时设置为 4s
      # 或者修改配置
      slow_query_log = ON
      long_query_time = 4
      slow_query_log_file = D:/mysql/mysql57-slow.log
      
      # 查找最近 10 条慢查询日志
      mysqldumpslow -s t -t 10 -g 'select' D:/mysql/mysql57-slow.log
      
  2. 分析 SQL 语句
    • 索引
      • where
      • group by
      • order by
    • SQL 语句
      • in 和 not in 优化成联合查询
      • 减少联合查询
    • 工作中不要用 age 字段,而是存储他的生日(年月日)

主键选择

  • innodb 中表是索引组织表,每张表有且仅有一个主键。
    • 如果显式设置 PRIMARY KEY,则该 key 作为该表的主键。
    • 如果没有显式设置,则从非空唯一索引中选择:
      • 只有一个非空唯一索引,则选择该索引为主键。
      • 有多个非空唯一索引,则选择声明的第一个作为主键。
    • 没有非空唯一索引,则自动生成一个 6 字节的 _rowid 作为主键。

约束

  • 为了实现数据的完整性,对于 innodb,提供了以下几种约束:
    primary keyunique keyforeign keydefaultnot null

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

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

相关文章

opencv的图像上下、左右和对角线翻转—flip函数

在OpenCV中&#xff0c;flip函数用于翻转图像。你可以沿x轴、y轴或两者同时翻转图像。这个函数非常直接&#xff0c;可以用于创建镜像图像或旋转图像。 void flip(InputArray src, OutputArray dst, int flipCode);src&#xff1a;输入图像。 dst&#xff1a;翻转后的输出图像…

安卓系统和iOS系统的手机备忘录同步数据方法

在这个智能手机时代&#xff0c;安卓与iOS系统犹如两位王者&#xff0c;各自拥有庞大的用户群体。有人钟情于安卓的开放与多样&#xff0c;有人偏爱iOS的流畅与稳定。甚至&#xff0c;有些人为了满足不同需求&#xff0c;同时使用着两个系统的手机。我就是其中的一员。 工作中…

ELK 简介安装

1、概念介绍 日志介绍 日志就是程序产生的&#xff0c;遵循一定格式&#xff08;通常包含时间戳&#xff09;的文本数据。 通常日志由服务器生成&#xff0c;输出到不同的文件中&#xff0c;一般会有系统日志、 应用日志、安全日志。这些日志分散地存储在不同的机器上。 日志…

RAW 编程接口 TCP 简介

一、LWIP 中 中 RAW API 编程接口中与 TCP 相关的函数 二、LWIP TCP RAW API 函数 三、LwIP_Periodic_Handle函数 LwIP_Periodic_Handle 函数是一个必须被无限循环调用的 LwIP支持函数&#xff0c;一般在 main函数的无限循环中调用&#xff0c;主要功能是为 LwIP各个模块提供…

LeetCode | 整数反转 C语言

Problem: 7. 整数反转 文章目录 思路解题方法Code结果 思路 运算部分 while(x > 0) {y x % 10;y * 10;x / 10; } y / 10;对于大于32位的数要用long int类型的变量保存用pow算-2的31次方和2的31次方-1。 解题方法 由思路得 Code int reverse(long int x){long int y …

bat 查找文件所在

脚本 在批处理文件&#xff08;.bat&#xff09;中查找文件所在的目录&#xff0c;你可以使用dir命令结合循环和条件语句来实现。以下是一个简单的示例&#xff0c;演示如何在批处理文件中查找指定文件并输出其所在目录&#xff1a; echo off setlocal enabledelayedexpansio…

预训练大模型LLM的PEFT之——LORA

简介 LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS&#xff0c;直接翻译过来就是大模型的低秩适配 2021年微软提出的LoRA&#xff0c;它的灵感来自于 Li和 Aghajanyan等人的一些关于内在维度&#xff08;intrinsic dimension&#xff09;的发现&#xff1a;模型是过参…

[HTML]Web前端开发技术27(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

大型语言模型的语义搜索(一):关键词搜索

关键词搜索(Keyword Search)是文本搜索种一种常用的技术&#xff0c;很多知名的应用app比如Spotify、YouTube 或 Google map等都会使用关键词搜索的算法来实现用户的搜索任务&#xff0c;关键词搜索是构建搜索系统最常用的方法&#xff0c;最常用的搜索算法是Okapi BM25&#x…

post请求向服务器发送JSON格式数据设置Content-Type

情景&#xff1a;与后台联调接口时&#xff0c;后台要求传递JSON格式的数据。 处理&#xff1a;我们进行XHR请求时需要设置请求头的Content-Type值为application/json&#xff0c;如下图所示。 浏览器查看具体请求与参数格式&#xff08;形式&#xff09;如下&#xff1a;

ubuntu20.04安装实时内核补丁PREEMPT_RT

参考&#xff1a; Ubuntu 18.04安装 RT-PREEMPT 实时内核及补丁【过程记录】_ubuntu18.04 preempt rt linux 5.6.19-CSDN博客 https://github.com/UniversalRobots/Universal_Robots_ROS_Driver/blob/master/ur_robot_driver/doc/real_time.md当前内核&#xff1a;5.15.0-94-ge…

ShardingSphere 5.x 系列【13】绑定表

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 概述2. 问题演示3. 绑定表1. 概述 关联查询是数据库查询中的一种常用操作…

企业微信变更企业主体的流程

企业微信变更主体有什么作用&#xff1f;做过企业运营的小伙伴都知道&#xff0c;很多时候经常会遇到现有的企业需要注销&#xff0c;切换成新的企业进行经营的情况&#xff0c;但是原来企业申请的企业微信上面却积累了很多客户&#xff0c;肯定不能直接丢弃&#xff0c;所以这…

00后编程交流qq群 欢迎广大编程爱好者加入

&#x1f680;【00后编程交流&兼职外包】&#x1f680; 链接直达&#xff1a; 点击此处加入群聊&#xff08;无需验证&#xff09; &#x1f4cc; 群简介&#xff1a; 欢迎加入【00后编程交流&兼职外包】QQ群&#xff01;这里是一个专为00后编程爱好者打造的交流平台…

装饰模式(Decorator Pattern)

定义 装饰模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许通过将对象包装在装饰器类的实例中来动态地添加新的行为和责任。这种模式可以在不修改现有代码的情况下&#xff0c;灵活地扩展对象的功能。 示例 考虑一个咖啡店的场景&…

设置主从复制时发生报错Could not find first log file name in binary log index file‘;解决方案

如图所示&#xff0c;slave_io_runnind:no,slave_sql_running:yes 此时&#xff0c;主从配置错误&#xff0c;我们可以查看Last_IO_Error:来查看报错信息 此时&#xff0c;我们需要停止从服务器的主从服务&#xff0c; mysql> stop slave; Query OK, 0 rows affected, 1 w…

【开源】JAVA+Vue.js实现医院门诊预约挂号系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 功能性需求2.1.1 数据中心模块2.1.2 科室医生档案模块2.1.3 预约挂号模块2.1.4 医院时政模块 2.2 可行性分析2.2.1 可靠性2.2.2 易用性2.2.3 维护性 三、数据库设计3.1 用户表3.2 科室档案表3.3 医生档案表3.4 医生放号…

VantUI组件的安装和使用

Vant UI 是一款轻量、可靠的移动端 Vue 组件库&#xff0c;适用于构建高性能的移动端页面。它提供了丰富的组件&#xff0c;如按钮、输入框、弹窗、轮播等&#xff0c;并且具有灵活的配置和扩展性。Vant UI 的设计风格简洁&#xff0c;易于上手&#xff0c;能够满足大部分移动端…

手拉手Vite+Vue3+TinyVue+Echarts+TailwindCSS

技术栈springboot3hutool-alloshi-coreVue3viteTinyVueEchartsTailwindCSS软件版本IDEAIntelliJ IDEA 2022.2.1JDK17Spring Boot3.1hutool-all5.8.18oshi-core6.4.1Vue35.0.10vite5.0.10axios1.6.7echarts5.4.3 ECharts是一个使用 JavaScript 实现的开源可视化库&#xff0c;可…

【网络编程】okhttp深入理解

newCall 实际上是创建了一个 RealCall 有三个参数&#xff1a;OkHttpClient&#xff08;通用配置&#xff0c;超时时间等&#xff09; Request(Http请求所用到的条件&#xff0c;url等) 布尔变量forWebSocket&#xff08;webSocket是一种应用层的交互方式&#xff0c;可双向交互…