MySQL 索引原理以及 SQL 优化

索引

  • 索引:一种有序的存储结构,按照单个或者多个列的值进行排序。
  • 索引的目的:提升搜索效率。
  • 索引分类:
    • 数据结构
      • 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.mfbz.cn/a/403743.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为OD机试真题-查找接口成功率最优时间段-2023年OD统一考试(C卷)--Python3--开源

题目&#xff1a; 考察内容&#xff1a; for 时间窗口list(append, sum, sort) join 代码&#xff1a; """ 题目分析&#xff1a;最长时间段 且平均值小于等于minLost同时存在多个时间段&#xff0c;则输出多个&#xff0c;从大到小排序未找到返回 NULL 输入…

PostgreSQL 的实体化视图介绍

PostgreSQL 实体化视图提供一个强大的机制&#xff0c;通过预先计算并将查询结果集存储为物理表来提高查询性能。本教程将使用 DVD Rental Database 数据库作为演示例子&#xff0c;指导你在 PostgreSQL中创建实体化视图。 了解实体化视图 实体化视图是查询结果集的快照&…

T-Dongle-S3开发笔记——分区表

参考&#xff1a; ESP32之 ESP-IDF 教学&#xff08;十三&#xff09;—— 分区表_esp32分区表-CSDN博客 分区表 - ESP32 - — ESP-IDF 编程指南 latest 文档 (espressif.com) 分区表是 ESP32 划分内部 flash 闪存的清单&#xff0c;它将 flash 划分为多个不同功能的区域用于…

【前端素材】推荐优质后台管理系统inspina平台模板(附源码)

一、需求分析 后台管理系统是一个集成了多种功能模块的系统&#xff0c;通过这些模块的协同工作&#xff0c;实现对网站、应用程序或系统的全面管理和控制。管理员通过后台管理系统可以高效地管理用户、内容、数据、权限等方面的工作&#xff0c;确保系统的正常运行和安全性。…

MariaDB落幕和思考

听过MySQL的基本也都知道 MariaDB。MariaDB由MySQL的创始人主导开发&#xff0c;他早前曾以10亿美元的价格&#xff0c;将自己创建的公司MySQL AB卖给了SUN&#xff0c;此后&#xff0c;随着SUN被甲骨文收购&#xff0c;MySQL的所有权也落入Oracle的手中。传闻MySQL的创始人担心…

【火猫TV】DOTA2-喀山未来运动会:LGD 战队2-0击败Neon

在2月22号进行的俄罗斯喀山未来运动会DOTA2项目淘汰赛上,LGD 战队以2-0击败Neon战队晋级下一轮。双方对阵第二局,LGD对线期三路优,中期圣堂小鱼越打越肥,轻松拿下了比赛的胜利,以下是对决战报。转载:火猫TV资讯https://www.huomaotv.com/ LGD战队在天辉,阵容是小鱼、圣堂、玛尔…

使用ffmpeg实现视频片段截取并保持清晰度

1 原始视频信息 通过ffmpeg -i命令查看视频基本信息 ffmpeg -i input.mp4 ffmpeg version 6.1-essentials_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developersbuilt with gcc 12.2.0 (Rev10, Built by MSYS2 project)configuration: --enable-gpl --enable-ve…

Python Web开发记录 Day2:CSS

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 二、CSS1、CSS-初始入门①快速了解②CSS应用方式…

SpringCloud(14)之SpringCloud Consul

我们知道 Eureka 2.X 遇到困难停止开发了&#xff0c;所以我们需要寻找其他的替代技术替代Eureka&#xff0c;这一小 节我们就讲解一个新的组件Consul。 一、Consul介绍 Consul 是 HashiCorp 公司推出的开源工具&#xff0c;用于实现分布式系统的服务发现与配置。与其它分布式…

横空出世,Bright Data 低代码数据平台,即将颠覆你的认知!

大家好&#xff0c;我是锋哥&#xff0c;最近接了个监控平台的私活项目。由于监控公开的站点太多&#xff0c;在我无从下手迷茫之际&#xff0c;竟然无意中发现了这个宝藏级低代码数据平台 - 亮数据。功能强大&#xff0c;性能炸裂&#xff01; 传统开发 以前我们开发这种监控…

文件上传漏洞--Upload-labs--Pass10--双写绕过

一、什么是双写绕过 顾名思义&#xff0c;双写绕过就是双写文件后缀名来进行绕过&#xff0c;如&#xff1a;test.php 双写后为 test.pphphp。通常情况下双写绕过用于绕过源代码中的 str_ireplace()函数。 二、双写绕过原理 1、首先进行代码审计&#xff0c;源代码中有黑名单…

HTML5 Canvas 限定文本区域大小,文字自动换行,自动缩放

<!DOCTYPE html> <html> <body><h1>HTML5 Canvas 限定文本展示范围、自动计算缩放字体大小</h1><div id"tips">0</div> <div id"content">良田千顷不过一日三餐广厦万间只睡卧榻三尺良田千顷不过一日三餐…

六、回归与聚类算法 - 岭回归

目录 1、带有L2正则化的线性回归 - 岭回归 1.1 API 2、正则化程度的变化对结果的影响 3、波士顿房价预测 线性回归欠拟合与过拟合线性回归的改进 - 岭回归分类算法&#xff1a;逻辑回归模型保存与加载无监督学习&#xff1a;K-means算法 1、带有L2正则化的线性回归 - 岭回…

ktorm + ktorm-ksp + springboot搭建RBAC后台模板 实践

本文代码仓库&#xff1a;https://github.com/okfanger/ktorm-ksp-springboot-demo 0. 前言 使用kotlin写springboot是前几个月突然萌生的想法&#xff0c;起因是看到了 ktorm 官网里的一个截图&#xff1a; 没错&#xff0c;你可以一眼看出这款 orm 框架的特点&#xff0c…

测斜孔造孔与测斜管安装有什么要求

在工程测量中&#xff0c;测斜孔的造孔和测斜管的安装是两个重要的环节&#xff0c;它们直接关系到测量结果的准确性和可靠性。为了确保测斜孔造孔和测斜管安装的质量&#xff0c;需要遵循一系列严格的要求和规范。 测斜孔的造孔应遵循以下要求&#xff1a;钻孔应呈铅直布置&am…

探索数据宝藏:填写《全国数据资源调查》的乐趣与技巧

2月19日&#xff0c;国家数据局等四部门发布关于开展全国数据资源调查的通知。通知提出&#xff0c;为贯彻落实《数字中国建设整体布局规划》工作部署&#xff0c;摸清数据资源底数&#xff0c;加快数据资源开发利用&#xff0c;更好发挥数据要素价值&#xff0c;国家数据局、中…

袋鼠云产品功能更新报告09期|更全面,更多样,更高效

欢迎阅读袋鼠云09期产品功能更新报告。在此期报告中&#xff0c;我们秉持创新与优化并重的理念&#xff0c;对产品进行了深度打磨与全面升级。每一处细节的改进&#xff0c;都是我们对卓越品质的不懈追求&#xff0c;期待这些新功能能助力您的业务运营与发展&#xff0c;让数字…

openssl 生成nginx自签名的证书

1、命令介绍 openssl req命令主要的功能有&#xff0c;生成证书请求文件&#xff0c; 查看验证证书请求文件&#xff0c;还有就是生成自签名证书。 主要参数 主要命令选项&#xff1a; -new :说明生成证书请求文件 -x509 :说明生成自签名证书 -key :指定已…

ChatGPT 是什么

文章目录 一、ChatGPT 是什么二、ChatGPT的发明者三、ChatGPT的运作方式四、ChatGPT的技术五、ChatGPT的优势六、ChatGPT的局限性七、ChatGPT的应用八、ChatGPT的未来九、总结 一、ChatGPT 是什么 OpenAI的ChatGPT&#xff0c;即Chat Generative Pre-Trained Transformer&…

React 模态框的设计(二)

自定义组件是每个前端开发者必备的技能。我们在使用现有框架时难免有一些超乎框架以处的特别的需求&#xff0c;比如关于弹窗&#xff0c;每个应用都会用到&#xff0c;但是有时我们使用的框架中提供的弹窗功能也是功能有限&#xff0c;无法满足我们的应用需求&#xff0c;今天…