根据索引进行MySQL查询的简单优化

news/2025/3/16 15:34:30/文章来源:https://www.cnblogs.com/meatplo/p/18775046

查询优化SQL

让SQL尽量可以命中索引,可以提示查询的效率(但是数据库如果不走索引的速度较快,就不会去走索引)

最左匹配法则

由于联合索引中包括了多个列,那么对于这多个列的匹配就有一定的规则,就是最左匹配法则,

在使用联合索引时,必须满足从左边开始匹配索引列。

假设现在存在以name,age,phone的联合索引

情况一:where name = ? and age = ? and phone = ?

​ where name = ? and phone = ? and age = ? ,

只要查询条件中包含了索引的全部列,并且使用and作为连接,那么就会命中全部索引(mysql对于这样的情况会自动优化sql来命中尽可能多的索引)

情况二:where name = ? and age = ? ,命中name和age两个索引

​ where name = ? and phone = ? , 只命中name一个索引

​ where age = ? and phone = ? , 没有命中索引

如果查询条件中只包含了部分索引列,并使用and作为连接,那么就会根据索引中列的顺序进行最左匹配,首先会看条件中有没有包含索引内的第一个列,依次后推,msql对于你的sql语句内的条件是会自动调优的,但是索引的匹配还是从左到右开始判断的,只要索引从左到右匹配有字段匹配不到,那么就不会命中后续的索引,不管你sql中的条件有没有包含后续的索引列,都不会继续匹配。

情况三:where name = ? and age = ? or phone = ? , 不会命中索引

不管你的条件有没有包含索引列,只有sql中出现了or,索引就会失效,可以通过把or换成 union[合并去重 + all 合并不去重] 来实现

select * from table_name where name = ? and age = ? union select * from table_name where phone = ? ,命中name和age索引

修改后实现的效果是一样的,但是可以让此sql命中部分索引


索引失效的情况

情况一: 使用了!=进行条件判断

原因:索引的底层是B+树,是一般是按照主键或者其他索引条件,从小到大,然后从左到右存储的,因此在查询的时候支持等值查询,来快速定位,或者范围查询来筛选出符合的数据,但是不等于的操作需要排除特定字段,从而筛选出其他字段,这样即无法满足等值匹配,也无法实现范围查询,从而导致索引失效。

情况二:在条件中使用了or关键字

原因:or会使查询的条件出现不确定性,对于索引来说希望的使条件较为确定的查询,但是or的出现会增了一定的复杂度,mysql内部的优化器就会不走索引,从而取全表扫描

情况三:使用is null 或者 is not null

原因:前者是由于索引存储的数据内是不会放null值的,后者原因则与不等于基本相同

情况四:对列数据做运算,使用了函数

原因:索引中存储的数据的表内字段的原始数据,在进行匹配时也只能满足等值匹配或范围查询,经过了计算后就无法匹配到原始值导致索引失效

情况五:模糊匹配使用了左%,如name like '%aaa'

原因:查询索引时是从左到右扫描的,%代表了不定长的前缀,这样会导致索引扫描过程中,无法排除无关的记录,最后的效果和全表扫描差不多,数据库就不会查询索引从而直接全表扫描

情况六:分页查询,数据量太大,如limit 999 ,100 是查询第999页的100条记录,而分页的底层实现是,先查出全部的100000记录,然后去除前99900,再拿到后面的100条记录。

情况七:使用in来进行等值查询索引时,里面的元素个数不能超过1000,根据阿里开发规约里面描述超过1000就会使索引失效

情况八:varcher类型,匹配时字符编码不一致


Explain关键词

EXPLAIN 是 MySQL 中用于分析查询执行计划的重要工具。通过 EXPLAIN,可以了解查询的性能瓶颈,并采取相应的优化措施。

效果如下:

image-20250316114219970

主要的字段:

1.type(索引类型)

  • 这条sql的连接的类型,性能由好到差为NULL、system、const、eq_ref、ref、range、 index、all
    • system:查询系统中的表
    • const:根据主键查询
    • eq_ref:主键索引查询或唯一索引查询
    • ref:索引查询
    • range:范围查询
    • index:索引树扫描
    • all:全盘扫描

image-20250316114459371

2.possible_keys:可能会用到的索引

3.key:实际命中索引

4.key_len: 最长索引宽度

  • 计算规则:

image-20250316142956555

5.Extra 额外的优化建议,提供额外的信息,描述查询的执行细节。

  • 常见值:
    • Using where:使用了 WHERE 子句过滤数据。
    • Using index:覆盖索引,查询只需从索引中获取数据,无需访问表。
    • Using temporary:使用了临时表(如排序或分组)。
    • Using filesort:需要额外的排序操作。
    • Using join buffer:使用了连接缓冲区。
    • Impossible WHERE:WHERE 子句始终为假,返回空结果集。

优化查询

基于上述一些规则和情况,可以优化对于的查询方式

  • 查询的条件尽可能命中索引
  • 使用联合索引时要遵循最左匹配法则
  • 要尽可能避免索引失效的出现
  • 对于分页查询的优化,比如现在每页有100个记录,我们要查询999页
    • 原本的方式:select column_1, column_2 from table_name limit 999,100 会导致索引失效
    • 优化的方式:已知主键为自增的就可以添加条件 select column_1, column_2 from table_name where id > 99899 limit 100 使主键索引生效
  • 尽可能避免回表查询
    • 回表:通过非主键索引查询到了主键,并且还需要查询非主键索引和主键以外的字段值时,就会通过主键索引再次查询数据,从而查询到对应的字段值
    • 使用覆盖索引:对于需要查询的字段,添加联合索引,这样就不会就会覆盖到原本的非主键索引,也不会取查询主键索引,解决了回表问题
      • 比如:目前给name创建了非主键索引
      • 查询语句为select id,name,age,gender from user where name = ? ,由于创建了非主键索引name,那么就会更加此非主键索引查询,由于索引的底层,基于非主键索引中存放的数据只有主键,因此只能查到主键,要想查到其他字段的值,就需要到主键索引内查出完整的数据,出现回表
      • 所以,我们可以为name,age,gender创建联合索引,这样根据name查询后,就可以直接从联合索引的索引中拿到需要的数据
    • 索引下推:在匹配索引的过程中,一般是根据索引列从左到右分部查询过滤,但是所有下推,会先判断全部的查询条件是否满足索引,如果全部满足或者部分满足,则会把这些满足所有的条件,一步之间过滤,而不是根据索列一个一个匹配过滤,从而提高了查询效率,MySQL5.6之后默认会开启,
      • 比如,目前有auther,price创建了联合索引
      • 查询语句为:select id from books where auther = ? and price > 100 , 如果没有索引下推,首先就会根据索引从左往右匹配,所有第一次回匹配到auther这字段,满足所有的匹配规则则会进行第一次过滤,之间交给后续的过滤规则接着匹配索引来查询,如果说在数据库内auther是张三的很多,但是价格大于100的可能就几个,那么就会使效率降低
      • 如果使用了索引下推,首先就会先查看全部的查询条件是否满足索引的匹配规则,满足则根据查询条件一次过滤,这样就会提高查询的效率。
      • 查看Extra中的值是 Using index condition,就表示触发了索引下推

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FastAPI依赖注入:参数共享与逻辑复用

扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长第一章:依赖注入核心原理 1.1 依赖树构建机制 from fastapi import Dependsdef auth_service():return OAuth2Scheme()def db_conn(auth: dict = Depends(auth_service)):return Database(creds=auth)@app.get(&q…

洛谷-P1449 后缀表达式

重操旧业~ 本菜鸡看到题就只会想到数组,但后来发现不可行,出去俩元素,还得进来一个元素,不好调o(╥﹏╥)o emm...但还是有所收获的,2转2,利用2-0,而不是直接强制int转换哦 同时也发现被题中举的例子迷惑了,数字可不一定是个位数! 1、此题采用栈和二叉树的后序遍历思想(…

DQL(查询语句)

简单查询 查询一个字段 select 字段名 from 表名; 查询多个字段 select 字段名1,字段名2,...,字段名 from 表名; 查询全部字段 ①在查询多个字段中,将所有的字段名写入 ②select * from 表名;————效率低,可读性差,因为将星号转化为所有字段名需要耗费一定时间,所…

PTA

​ 题目描述 小轿车中有一个系统随时监测四个车轮的胎压,如果四轮胎压不是很平衡,则可能对行车造成严重的影响。让我们把四个车轮 —— 左前轮、右前轮、右后轮、左后轮 —— 顺次编号为 1、2、3、4。本题就请你编写一个监测程序,随时监测四轮的胎压,并给出正确的报警信息。…

第二章

TempStr = input("请输入带有符号的温度值:") if isinstance(TempStr, str) and TempStr[-1] in [F, f]:C = int((float(TempStr[0:-1]) - 32) / 1.8)print(f"转换后的温度是{C}C") elif isinstance(TempStr, str) and TempStr[-1] in [C, c]:F = int(1.8…

window11家庭版 WSL上安装CentOS7

环境 Windows11家庭版 1. 安装WSL配置 1.1 Win命令模式开启虚拟化步骤点击查看代码 # 启用适用于 Linux 的 Windows 子系统:打开powershell并输入: dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart# 启用虚拟化:以管理员打…

探秘Transformer系列之(14)--- 残差网络和归一化

从零开始解析Transformer,目标是:(1) 解析Transformer如何运作,以及为何如此运作,让新同学可以入门;(2) 力争融入一些比较新的或者有特色的论文或者理念,让老鸟也可以有所收获。探秘Transformer系列之(14)--- 残差网络和归一化 目录探秘Transformer系列之(14)--- 残差…

省选联考2024游记

搬运自 洛谷博客 ,文章写于 2024.03.05“总有地上的生灵,敢于直面雷霆的威光。”全文共1169字。 Day -105 2023/11/18 noip考完人就崩了,第二题甚至都没写出正解,只有压线省一,大哭。 也基本注定这回是进不了省队了。 Day -5 2024/2/26 周一 开始停课 Day -4 2024/2/27 周…

day30 正则三剑客---awk

awk是什么 再谈三剑客grep,擅长单纯的查找或匹配文本内容 sed,更适合编辑、处理匹配到的文本内容 awk,更适合格式化文本内容,对文本进行复杂处理后、更友好的显示三个命令称之为Linux的三剑客 awk学完后的能力 以下部分内容需要结合shell编程对文本行数据提取数据字段 模式…

树上查分学习笔记+做题记录

树上查分 点的查分求路径 \(u-v\) 上的点被经过的次数. \(cnt[x]\) 表示点 \(x\) 被经过的次数. 核心代码:cnt[u]++; cnt[v]++; cnt[lca(u,v)]--; cnt[father[lca(u,v)]]--;A. 运输压力解法 树上查分板子题啊 #include <bits/stdc++.h> using namespace std; const int N…

ActAgent开发之基于http请求引用链路模版发起对话

下载deepeek 首先本地安装ollama,这是一款支持mac,windows和linus系统的大模型管理工具。下载好后打开终端,执行命令ollama pull deepseek-r1:7b,可以在网上找想要下载的开源大模型,我这里下载的是deepseek-r1的7b模型。执行完后可以用ollama list查看是否下载成功,然后可…

缓存与数据库的一致性方案,Redis与Mysql一致性方案,大厂P8的终极方案(图解+秒懂+史上最全)

说在前面 在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的redis一致性面试题,类似如下:如何保障 MySQL 和 Redis 的数据一致性? 如何保障 MySQL 和 Cache 的数据一…