【MySQL】索引使用规则——(覆盖索引,单列索引,联合索引,前缀索引,SQL提示,数据分布影响,查询失效情况)

前言

大家好吖,欢迎来到 YY 滴MySQL系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁

主要内容含:

欢迎订阅 YY滴C++专栏!更多干货持续更新!以下是传送门!

目录

一.索引使用规则

※.验证索引效率提升

  • 在未建立索引之前,执行如下SOL语句,查看SQL的耗时
  • 耗时11s
  • 利用主键索引(id)查,耗时0s
  • 利用第二个字段sn查,耗时21s,性能极低
  • 针对字段sn创建索引,然后再次执行相同的SQL语句,再次查看SQL的耗时
  • 从21s变成0.01s,性能大大提升


1.覆盖索引------查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到

  • 尽量使用覆盖索引**(查询使用了素引,并且需要返回的列,在该索引中已经全部能够找到)**,减少select *

演示:

  • 我们查看索引
  • 紫色部分:上面比下面的效率好
  • 多出的蓝色部分(返回的列),不能够在在该索引中找到,上部分的效率比下部分高
  • 上部分:usingindexcondition:查找使用了索引,但是需要回表查询数据
  • 下部分 :using where;using index:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据

2.单列索引&联合索引

  • 单列索引:即一个索引只包含单个列。
  • 联合家引:即一个索引包含了多个列。
  • 在业务场景中,如果存在多个查询负件,考虑针对于查询字段建立索引时,建议优先建立联合索引,而非单列引。
  • **多条件联合查询时,MySQL优化器会评估哪个字段的索引效率更高,会选择该索引完成本次查询。**要强制就用可视日志。

演示:

  • name和phone字段,都是单列索引,但只用到一个字段索引
  • 我们给name和phone字段创建联合索引,MySQL优化器会评估哪个字段的索引效率更高。如果我们要主动设置SQL语句用的索引,涉及到下文我们提到的SQL提示

3.前缀索引------解决冗长字符串与索引问题

【1】前缀索引&索引选择性的介绍

  • 当字段类型为字符串(varchar,text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO,影响查询效率。
  • 此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
  • 如下图,计算可得字段选择性是1
  • 不断调整substring截取部分,可得到不同选择性

【2】前缀索引创建演示:

  • 针对email字段截取字符串,建立前缀索引,降低索引体积
  • 建立前五个字符构成的前缀索引
  • 查询发现用到了创建的前五个字符构成的前缀索引

5.SQL提示------指定某个索引/忽略索引/强制索引

  • SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。
  • 例如下图SQL执行计划,可能索引有两个,但是最终应用的索引只有一个,某些情况下我们就是要指定用某个索引

演示:

  • 有这样一张表,我们看下这段SQL的执行计划,索引是复合索引idx_user_pro_age_sta
  • 我们针对profession创建一个单列索引
  • 我们想要用这个单列索引,我们就建议索引use XX------MySQL不一定接受,要强制用force XX

6.数据分布影响------MySQL自我评估

  • 如果MySQL评估使用索引比全表更慢,则不使用索引

演示:

  • 有一张表,我们关注其phone字段
  • 当我们进行不同的范围查询时,MySQL会自己选择用不用索引
  • 例如绿色部分用了联合索引,而红色部分要查找的数目已经大于总数一半了,此时MySQL自己选择全表扫描

7.查询失效的几种情况

【1】违背------最左前缀法则(联合索引)

  • 如果索引了多列(联合索引),要遵守最左前缀法则。
  • 最左前缀法则指的是查询从索引的最左列开始**(最左列存在即可)**,并且不跳过索引中的列,索引才不会失效
  • 如果跳跃某一列,索引将部分失效**(后面的字段索引失效)**

演示:

  • 有如下表
  • 查看索引,有一个age字段和status字段的联合索引idx_user_pro_age_sta
  • 联合索引生效,索引长度为54
  • 去掉status条件后,索引长度为49,因此可以判断status部分对应的索引长度为5
  • 去掉status和age条件后,索引长度为47,因此可以判断age部分对应索引长度为2

索引失效:

  • 索引的最左列不存在,key为null,不走索引,走全表扫描

  • 去除掉age,也会走联合索引,但是长度只有47,只有profession部分走索引,部分失效

  • 注:索引的最左列只要存在即可,顺序无所谓

【2】范围查询右侧失效

  • 联合索引中,出现范围查询(>,<),查询范围右侧的列索引失效
  • 实际中应该规避(>,<),在业务允许的范围下使用(>=,<=),(>=,<=)不会失效****

演示:

  • 如下图,联合索引正常长度应该是54,图中是49,说明没有走status索引------status索引失效了
  • 如下图,采用>=,索引长度为54,说明**>=的范围查询不会让右侧失效**

【3】用or分割开的条件,or后面没索引,所有索引失效

  • 如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到
  • 例如:age无索引,但是主键索引仍然不会生效

【4】索引列上进行运算操作,索引失效

  • 不要在索引列上进行运算操作,索引将失效

演示:

  • 有这样一张表,我们关注phone字段
  • phone是单列索引,发现用上了
  • 我们想要找手机号最后两位是15的,利用substring函数运算截取,第十位开始,截2位
  • 索引失效

【5】字符串类型字段使用时,不加引号,索引失效

  • 字符串类型字段使用时,不加引号,索引失效

演示:

  • phone是varchar类型,不加单引号,也能查
  • 但是由于存在隐式类型转换,索引会失效

【6】头部模糊匹配,索引失效

  • 如果仅仅是尾部模糊匹配,索引不会失效
  • 如果是头部模糊匹配,索引失效
相关推荐
Ren_xixi8 分钟前
redis和mysql的区别
数据库·redis·mysql
FF在路上28 分钟前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
真的很上进35 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
m0_7482338840 分钟前
SQL语句整理五-StarRocks
数据库·sql
众拾达人1 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.1 小时前
Mybatis-Plus
java·开发语言
不良人天码星1 小时前
lombok插件不生效
java·开发语言·intellij-idea
守护者1702 小时前
JAVA学习-练习试用Java实现“使用Arrays.toString方法将数组转换为字符串并打印出来”
java·学习
源码哥_博纳软云2 小时前
JAVA同城服务场馆门店预约系统支持H5小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台
禾高网络2 小时前
租赁小程序成品|租赁系统搭建核心功能
java·人工智能·小程序