MYSQL的索引使用注意

2023-11-18

索引并不是时时都会生效的,比如以下几种情况,将导致索引失效 

最左前缀法则

如果使用了联合索引,要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始, 并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效( 后面的字段索引失效 ) 。查看tb_user 表所创建的索引 。 这个联合索引涉及到三个字段,顺序分别为:profession,age,status。
show index from tb_user;

对于最左前缀法则指的是,查询时,最左变的列,也就是profession必须存在,否则索引全部失效。

 explain select * from tb_user where profession = '软件工程' and age = 31 and status = '0';

SQL 查询时,存在 profession 字段,最左边的列是存在的,索引满足最左前缀法则的基本条
件。但是查询时,跳过了 age 这个列,所以后面的列索引是不会使用的,也就是索引部分生效,所以索引的长度就是47
explain select * from tb_user where profession = '软件工程' and status = '0';

思考 

当执行 SQL 语句 : explain select * from tb_user where age = 31 and status = '0' and profession = '软件工程 ' ; 时,是否满足最左前缀法则,走不走联合索引,
可以看到,是完全满足最左前缀法则的,索引长度 54 ,联合索引是生效的。注意 : 最左前缀法则中指的最左边的列,是指在查询时,联合索引的最左边的字段( 即是第一个字段) 必须存在,与我们编写 SQL 时,条件编写的先后顺序无关。

范围查询

联合索引中,出现范围查询 (>,<) ,范围查询右侧的列索引失效。
explain select * from tb_user where profession = '软件工程' and age > 30 and status = '0' ;

当范围查询使用 > < 时,走联合索引了,但是索引的长度为 49 ,就说明范围查询右边的 status
段是没有走索引的。
explain select * from tb_user where profession = '软件工程' and age >= 30 and status = '0';

当范围查询使用 >= <= 时,走联合索引了,但是索引的长度为 54,就说明所有的字段都是走索引的。 所以,在业务允许的情况下,尽可能的使用类似于 >= <= 这类的范围查询,而避免使用 > <

索引列运算

不要在索引列上进行运算操作, 索引将失效。在tb_user表中,除了前面介绍的联合索引之外,还有一个索引,是phone字段的单列索引。

当根据 phone 字段进行等值匹配查询时 , 索引生效。
explain select * from tb_user where phone = '17799990015';

当根据phone字段进行函数运算操作之后,索引失效。

explain select * from tb_user where substring(phone,10,2) = '15';

字符串不加引号

字符串类型字段使用时,不加引号,索引将失效。
字符串类型的字段,加单引号
 explain select * from tb_user where profession = '软件工程' and age = 31 and status = '0';

 字符串类型的字段,不加单引号

 explain select * from tb_user where profession = '软件工程' and age = 31 and status = '0';

我们会明显的发现,如果字符串不加单引号,对于查询结果,没什么影响, 但是数据库存在隐式类型转换,索引将失效。

模糊查询

如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。
模糊查询时, % 加在关键字之后
explain select * from tb_user where profession like '软件%';
模糊查询时, % 加在关键字之前
explain select * from tb_user where profession like '%工程';

我们发现,在 like 模糊查询中,在关键字后面加 % ,索引可以生效。而如果在关键字
前面加了 % ,索引将会失效。

or连接条件

or 分割开的条件, 如果 or 前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。
explain select * from tb_user where id = 10 or age = 23;

由于age没有索引,所以即使idphone有索引,索引也会失效。所以需要针对于age也要建立索引。

create index idx_user_age on tb_user(age);

 

再次执行上述的SQL语句

 or连接的条件,左右两侧字段都有索引时,索引才会生效。

数据分布影响

如果 MySQL 评估使用索引比全表更慢,则不使用索引。
explain select * from tb_user where phone >= '17799990005';
explain select * from tb_user where phone >= '17799990015';

MySQL 在查询时,会评估使用索引的效率与走全表扫描的效率,如果走全表扫描更快,则放弃
索引,走全表扫描。 因为索引是用来索引少量数据的,如果通过索引查询返回大批量的数据,则还不如走全表扫描来的快,此时索引就会失效。

 SQL提示

SQL 提示,是优化数据库的一个重要手段,简单来说,就是在 SQL 语句中加入一些人为的提示来达到优化操作的目的。

use index

建议 MySQL 使用哪一个索引完成此次查询(仅仅是建议, mysql 内部还会再次进行评估)
explain select * from tb_user use index(idx_user_pro) where profession = '软件工程';

 ignore index

忽略指定的索引。
explain select * from tb_user ignore index(idx_user_pro) where profession = '软件工程';

force index

强制使用索引。

explain select * from tb_user force index(idx_user_pro) where profession = '软件工程';

覆盖索引

尽量使用覆盖索引,减少 select * 。 那么什么是覆盖索引呢? 覆盖索引是指 查询使用了索引,并
且需要返回的列,在该索引中已经全部能够找到 。

查询id,profession,age, status字段

explain select id,profession,age, status from tb_user where profession = '软件工程' and age = 31 and status = '0' ;

 查询id,profession,age, status,name字段

explain select id,profession,age, status,name from tb_user where profession = '软件工程' and age = 31 and status = '0' \G;
因为,在 tb_user 表中有一个联合索引 idx_user_pro_age_sta ,该索引关联了三个字段profession、 age status ,而这个索引也是一个二级索引,所以叶子节点下面挂的是这一行的主键id 。 所以当我们查询返回的数据在 id profession age status 之中,则直接走二级索引 直接返回数据了。 如果超出这个范围,就需要拿到主键 id,再去扫描聚集索引,再获取额外的数据了,这个过程就是回表。 而我们如果一直使用select * 查询返回所有字段值,很容易就会造成回表查询(除非是根据主键查询,此时只会扫描聚集索引)

前缀索引

当字段类型为字符串( varchar text longtext 等)时,有时候需要索引很长的字符串,这会让
索引变得很大,查询时,浪费大量的磁盘 IO , 影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。

语法

create index idx_xxxx on table_name(column(n)) ; 1

前缀长度

可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高, 唯一索引的选择性是1 ,这是最好的索引选择性,性能也是最好的。
select count(distinct substring(email,1,5)) / count(*) from tb_user ;

创建前缀索引

create index idx_email_5 on tb_user(email(5));

单列索引与联合索引

  • 单列索引:即一个索引只包含单个列。
  • 联合索引:即一个索引包含了多个列。

我们先来看看 tb_user 表中目前的索引情况, 在查询出来的索引中,既有单列索引,又有联合索引。

在业务场景中,如果存在多个查询条件,考虑针对于查询字段建立索引时,建议建立联合索引, 而非单列索引。

总结

  1. 针对于数据量较大,且查询比较频繁的表建立索引。
  2. 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立引。
  3. 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
  4. 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
  5. 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间, 避免回表,提高查询效率。
  6. 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。
  7. 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MYSQL的索引使用注意 的相关文章

  • 我的表是什么 ROW_FORMAT?

    我发现MySQL有多行格式 http dev mysql com doc refman 5 1 en data size html 并且可以指定或更改它 另外 默认的 ROW FORMAT 显然随着 MySQL 版本的变化而改变 这是可以理
  • MAMP Pro mysql 无法启动

    我遇到问题无法找到解决此问题的方法 我收到这个错误 2017 01 11 23 58 25 7fffbac563c0 InnoDB Operating system error number 2 in a file operation In
  • 跨数据库管理系统检查字符串是否为数字的方法

    好的 我有这个字段 code varchar 255 它包含我们导出例程中使用的一些值 例如 DB84 DB34 3567 3568 我需要仅选择自动生成的 全数字 字段 WHERE is numeric table code is num
  • 为什么我的 php 代码无法连接到远程 MySql 数据库?

    我正在尝试连接到远程 MySql 数据库 但收到以下错误消息 警告 mysqli connect HY000 2002 连接尝试失败 因为连接方在一段时间后没有正确响应 或者由于连接的主机未能响应而建立的连接失败 在 C myLocalDi
  • 如何使用 Sequel Pro 在导入过程中将字符串更改为日期?

    我正在尝试使用 Sequel Pro 将文件导入到 MySQL 表中 我知道我需要使用 STR TO DATE 但我无法找出正确的语法 我在每一行都收到一堆这样的错误 ERROR in row 1 You have an error in
  • Mysql:多个表还是一张大表?

    这个问题已经被问过 但我还没有找到 1 个语音答案 最好这样做 1 张大桌子 其中 用户 ID 属性 1 属性 2 属性 3 属性 4 或 4 个小桌子 其中 用户 ID 属性 1 用户 ID 属性 2 用户 ID 属性 3 用户 ID 属
  • 当我将 xx 添加到 mysql float 列时,结果错误,这是一个错误吗?

    我的mysql 5 6 16 我的餐桌信息 CREATE TABLE xxx uid int 11 NOT NULL money float 10 2 NOT NULL DEFAULT 0 00 real money float 10 2
  • #1214 - 使用的表类型不支持 FULLTEXT 索引

    我收到一条错误消息 指出该表类型不支持 FULLTEXT 索引 我怎样才能实现这个目标 这是我的桌子 CREATE TABLE gamemech chat id bigint 20 unsigned NOT NULL auto increm
  • Rails 创建 schema_migrations - Mysql2::Error: 指定的键太长

    我正在使用Rails 3 2 6和Mysql 6 0 9 但我在MySQL 5 2 25上有完全相同的错误 当我创建新数据库时 rake db create 然后当我尝试加载架构时 rake schema load 我收到此错误 Mysql
  • 使用 Coldfusion 分页

    是否可以仅使用一个查询在 Coldfusion 中分页并显示页数 我的理解是 您显然可以使用一个查询进行分页 但您需要一个额外的查询来创建页面 这是为了计算结果总数 currentPage 1 resultsPerPage Offset i
  • 提高mysql导入速度[关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我有一个很大的数据库22GB 我曾经用过进行备份mysqldumpgzip 格式的命令 当我提取 gz 文件时 它会生成 sql文件的
  • sqlalchemy 中的随机 ID(pylon)

    我正在使用 pylons 和 sqlalchemy 我想知道如何将一些随机 id 作为primary key 最好的方法是使用随机生成的 UUID import uuid id uuid uuid4 uuid 数据类型在某些数据库中本机可用
  • REPLACE MYSql 中的新行字符不起作用

    我执行了以下查询 由于某种原因它没有替换数据库中的换行符 它说 Rows matches 1 但没有变化 有什么问题吗 mysql gt UPDATE aboutme SET abouttext REPLACE abouttext n WH
  • 在 ADO 查询 (mysql/MyConnector) 中使用参数

    今天我下载并安装了 MyConnector 这样我就可以通过 ADO 使用 Mysql 一切都安装好了 我可以与 ODBC 连接并从我的 delphi 环境进行连接 当我在运行时构建查询时 我收到一条错误消息 项目 Project1 exe
  • 主机 localhost 不允许连接到此 MySQL 服务器 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我不小心删除了我的用户表 删除了所有用户 现在每当我尝试访问我的数据库时 它都会说 主机本地主机不允许连接到此 MYSQL 服务器 我试过
  • 使用 PHP 将文件上传到 MySql DB

    我希望用户通过我在后端使用 MySql 用 PHP 开发的 web 应用程序上传文件 我想将文件存储在数据库中 我在这样做时遇到了问题 此外 一旦文件存储在数据库中 我们如何下载它 并在 web 应用程序中正确显示它 文件类型和文件的其他属
  • 存储过程函数中的动态表名

    我编写了一个存储过程函数来从表中获取名称 问题是我希望将表名作为参数传入 有几个不同的表我需要使用此函数 DELIMITER CREATE DEFINER root localhost FUNCTION getName tableName
  • 将 Python 列表(JSON 或其他)插入 MySQL 数据库

    所以我在Python中有一堆数组数据 嗯 相反 我有一个清单 我试图将此数组存储到 MySQL 数据库中的单个单元格中 我尝试使用 JSON 来序列化我的数据 但也许我不明白 JSON 是如何工作的 因此 在连接到我的数据库后 我尝试了上游
  • 如何使用外连接和分组依据在查询中包含 NULL 值

    我有两个表 其中包含以下示例数据 Table 1 item name item id item desc 1 apple 2 orange 3 banana 4 grape 5 mango Table 2 user items user i
  • 选择每组最新的项目[重复]

    这个问题在这里已经有答案了 可能的重复 检索每组中的最后一条记录 https stackoverflow com questions 1313120 retrieving the last record in each group 我有 2

随机推荐

  • Consul的简介与安装

    1 Consul简介 Consul是一套开源的分布式服务发现和配置管理系统 由HashiCorp公司用Go语言开发 Consul提供了微服务系统中的服务治理 配置中心 控制总线等功能 这些功能中的每一个都可以根据需要单独使用 也可以一起使用
  • wsl配置

    文章目录 1 systemd服务开启 2 固定IP 2 1 官网的方案 2 2 通过WSL2的Linux子系统设置静态IP 2 3 其他方案 3 运行 Linux GUI 应用安装 Chrome 浏览器 此文接我放弃了VMware 1 sy
  • vue(3)调整 App.vue 文件和router路由

    调整 App vue 文件 我们先把默认项目里面没用的东西先删除掉 把代码调整为下面的样子
  • js延迟加载的性能优化

    js的延迟加载有助于提高页面的加载速度 特别是竞价优化站是有一定的好处 今天来说说我是如何优化竞价站打开速度 案例 http yzmb pengchenggroup cn 动态创建DOM方式
  • 每日一题——有向网的邻接矩阵、邻接表、逆邻接表创建、打印及深度、广度遍历

    有向网的三种创建和深度广度遍历 include
  • 基于骨骼的行为识别笔记(NTU RGBD数据集解析)

    目录 1 人类行为 层次 2 输入数据 3 基于骨架的行为识别 4 数据集 4 1 NTU RGBD 4 1 1 下载方式 4 1 2 Benchmark 5 相关论文 5 1 Skeleton based Action Recogniti
  • JavaScript的设计模式解析——工厂模式

    这几天一直在看 JavaScript高级程序设计 在第六章面向对象的程序设计中 自我感觉对于小白而而言 会一定程度的难以理解 什么意思啊 根本不明白哇等等 注意 大神请略过 小小码农 不敢妄言 首先 我们开门见山 什么是工厂模式 工厂模式能
  • javascript中Math.random()产生随机数及parseInt的作用

    Math random 是令系统随机选取大于等于 0 0 且小于 1 0 的小数 即 0 0 1 0 Math floor 返回小于参数x的最大整数 即对浮点数向下取整 比如Math floor 3 8 为3 一 在连续整数中取得一个随机整
  • WIN10 系统的 IRQL NOT LESS OR EQUAL 蓝屏问题

    WIN10 系统的 IRQL NOT LESS OR EQUAL 蓝屏问题 请参考以下步骤 1 Win r 输入 msconfig 2 点击 服务 标签卡 选择 隐藏所有的微软服务 然后点击全部禁用 若您启用了指纹识别功能 请不要关闭相关服
  • c#基础知识---多线程

    线程 被定义为程序的执行路径 每个线程都定义了一个独特的控制流 如果您的应用程序涉及到复杂的和耗时的操作 那么设置不同的线程执行路径往往是有益的 每个线程执行特定的工作 线程是轻量级进程 一个使用线程的常见实例是现代操作系统中并行编程的实现
  • Windows11 安装 WSA 简单上手一试

    Win11 安装 WSA 安卓子系统 教程 参考 http www xitongzhijia net xtjc 20211008 228813 html 上手需要一些 命令行 基础 大概了解 WSL WSA Hyper V 等概念 微软尚未
  • 模糊控制规则表是怎么确定的_模糊控制

    1 模糊控制的基本原理 模糊控制是以模糊集理论 模糊语言变量和模糊逻辑推理为基础的一种智能控制方法 它是从行为上模仿人的模糊推理和决策过程的一种智能控制方法 该方法首先将操作人员或专家经验编成模糊规则 然后将来自传感器的实时信号模糊化 将模
  • 空洞卷积(Atrous convolution)

    目录 空洞卷积 空洞卷积优点 Dilated Convolution存在的问题 空洞卷积 空洞卷积是针对图像语义分割问题中下采样会降低图像分辨率 丢失信息而提出的一种卷积思路 利用添加空洞扩大感受野 让原本3x3的卷积核 在相同参数量和计算
  • PyQt5模块构成

  • c语言求数字b在a中出现次数,编写一个函数void fun(char *tt,int pp[]),统计在tt字符中"a"到"z"26各字母各自出现的次数,并依次放在pp所指的数组中。...

    满意答案 yjj0h044 2015 09 26 采纳率 50 等级 8 已帮助 961人 void fun char tt int pp int i for i 0 i 26 i pp i 0 while tt switch tt cas
  • Failed to execute ‘drawImage‘ on ‘CanvasRenderingContext2D‘: The image argument is a canvas element

    Echarts重绘报错 原因在于绘制时 未正确获取到画布的宽高 可在容器内写入行内样式 即可解决
  • 《Windows驱动开发技术详解》之读写操作

    缓冲区方式读写操作 设置缓冲区读写方式 读写操作一般是由ReadFile和WriteFile函数引起的 这里先以WriteFile函数为例进行介绍 WriteFile要求用户提供一段缓冲区 并且说明缓冲区的大小 然后WriteFile将这段
  • 前端将下载的文件压缩为zip文件

    本来的话这个前端下载文件是要从后端的接口获取二进制流数据 再进行操作的 但是懒得自己写接口返回二进制流数据 就用了比较偷懒的方法来模拟这个二进制流数据 直接用原生的input就可以 类型选择为file 然后点击这个input 就可以拿到fi
  • 河北专接本微机原理错题整理及资料分享

    菜鸡经验分享 ps 我是边上班边接本总分352 专业课发挥失误 哎 专业微机原理没技巧就是背 多背多刷题 资料中的15套题多刷几遍 视频看b站鸡哥的就行 数学98 哪年考的都不难题型都差不多 资料中的卷子多刷刷就行 刷的时候必须满分 英语2
  • MYSQL的索引使用注意

    索引并不是时时都会生效的 比如以下几种情况 将导致索引失效 最左前缀法则 如果使用了联合索引 要遵守最左前缀法则 最左前缀法则指的是查询从索引的最左列开始 并且不跳过索引中的列 如果跳跃某一列 索引将会部分失效 后面的字段索引失效 查看tb