MySQL使用索引的最佳指南

news2024/9/22 5:30:13

MySQL使用索引的最佳指南

  • 1.选择合适的字段创建索引
  • 2.尽可能的考虑建立联合索引而不是单列索引
  • 3.注意避免冗余索引
  • 4.考虑在字符串类型的字段上使用前缀索引代替普通索引
  • 5.索引失效的情况

1.选择合适的字段创建索引

  1. 不为 NULL 的字段 :索引字段的数据应该尽量不为 NULL,因为对于数据为 NULL 的字段,数据库较难优化。如果字段频繁被查询,但又避免不了为 NULL,建议使用 0,1,true,false 这样语义较为清晰的短值或短字符作为替代。
  2. 被频繁查询的字段 :我们创建索引的字段应该是查询操作非常频繁的字段。
  3. 被作为条件查询的字段 :被作为 WHERE 条件查询的字段,应该被考虑建立索引。
  4. 频繁需要排序的字段 :索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
  5. 被经常频繁用于连接的字段 :经常用于连接的字段可能是一些外键列,对于外键列并不一定要建立外键,只是说该列涉及到表与表的关系。对于频繁被连接查询的字段,可以考虑建立索引,提高多表连接查询的效率。
  6. 数据表的主键,最好选用带顺序性的值,而不是使用UUID
  7. 如果实在需要使用非主键字段查询,那么尽量要写明查询的结果字段,而并非使用*

虽然索引能带来查询上的效率,但是维护索引的成本也是不小的。 如果一个字段不被经常查询,反而被经常修改,那么就更不应该在这种字段上建立索引了😨


2.尽可能的考虑建立联合索引而不是单列索引

因为索引是需要占用磁盘空间的,可以简单理解为每个索引都对应着一颗 B+树。如果一个表的字段过多,索引过多,那么当这个表的数据达到一个体量后,索引占用的空间也是很多的,且修改索引时,耗费的时间也是较多的。如果是联合索引,多个字段在一个索引上,那么将会节约很大磁盘空间,且修改数据的操作效率也会提升。

联合索引存在的矛盾:

联合索引存在一个致命的问题,比如在用户表中,通过id、name、age三个字段建立一个联合索引,此时来了一条查询SQL,如下:

SELECT * FROM `users` WHERE name = "meimei" AND age = "18";

而这条SQL语句是无法使用联合索引的,为什么呢?因为查询条件中,未包含联合索引的第一个字段,想要使用联合索引,那么查询条件中必须包含索引的第一个字段,如下:

SELECT * FROM `users` WHERE name = "meimei" AND id = 6;

因此在建立索引时也需要考虑这个问题,确保建立出的联合索引能够命中率够高。

建立联合索引时,一定要考虑优先级,查询频率最高的字段应当放首位🤯

同时,MySQL的最左前缀原则,才匹配到范围查询时会停止匹配,比如>、<、between、like这类范围条件,并不会继续使用联合索引,举个栗子:

SELECT * FROM tb WHERE X="..." AND Y > "..." AND Z="...";

当执行时,虽然上述SQL使用到X、Y、Z作为查询条件,但由于Y字段是>范围查询,因此这里只能使用X索引,而不能使用X、Y或X、Y、Z索引。


3.注意避免冗余索引

冗余索引指的是索引的功能相同,能够命中索引(a, b)就肯定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city )和(name )这两个索引就是冗余索引,能够命中前者的查询肯定是能够命中后者的 在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。


4.考虑在字符串类型的字段上使用前缀索引代替普通索引

前缀索引仅限于字符串类型,较普通索引会占用更小的空间,所以可以考虑使用前缀索引带替普通索引。

前缀索引虽然带来了节省空间的好处,但也正由于其索引节点中,未存储一个字段的完整值,所以MySQL也无法通过前缀索引来完成ORDER BY、GROUP BY等分组排序工作,同时也无法完成覆盖扫描等操作😩


5.索引失效的情况

但想要查看一条SQL是否使用了索引,需要用到一个自带的分析工具ExPlain

例如:

EXPLAIN SELECT * FROM `zz_users`;
+----+-------------+----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | zz_users | ALL  | NULL          | NULL | NULL    | NULL |    3 |       |
+----+-------------+----------+------+---------------+------+---------+------+------+-------+
  • id:这是执行计划的ID值,这个值越大,表示执行的优先级越高。
  • select_type:当前查询语句的类型,有如下几个值:
    simple:简单查询。
    primary:复杂查询的外层查询。
    subquery:包含在查询语句中的子查询。
    derived:包含在FROM中的子查询。
  • table:表示当前这个执行计划是基于那张表执行的。
  • type:当前执行计划查询的类型,有几种情况:
    all:表示走了全表查询,未命中索引或索引失效。
    system:表示要查询的表中仅有一条数据。
    const:表示当前SQL语句的查询条件中,可以命中索引查询。
    range:表示当前查询操作是查某个区间。
    eq_ref:表示目前在做多表关联查询。
    ref:表示目前使用了普通索引查询。
    index:表示目前SQL使用了辅助索引查询。
  • possible_keys:执行SQL时,优化器可能会选择的索引(最后执行不一定用)。
  • key:查询语句执行时,用到的索引名字。
  • key_len:这里表示索引字段使用的字节数。
  • ref:这里显示使用了那种查询的类型。
  • rows:当前查询语句可能会扫描多少行数据才能检索出结果。
  • Extra:这里是记录着额外的一些索引使用信息,有几种状态:
    using index:表示目前使用了覆盖索引查询。
    using where:表示使用了where子句查询,通常表示没使用索引。
    using index condition:表示查询条件使用到了联合索引的前面几个字段。
    using temporary:表示使用了临时表处理查询结果。
    using filesort:表示以索引字段之外的方式进行排序,效率较低。
    select tables optimized away:表示在索引字段上使用了聚合函数。

索引失效也是慢查询的主要原因之一,常见的导致索引失效的情况有下面这些:

  • 使用 SELECT * 进行查询;
  • 在索引列上进行计算(+、-、*、/、!.....)、函数、类型转换等操作;
  • % 开头的 LIKE 查询比如 like '%abc';;
  • 查询条件中使用 or,且 or 的前后条件中有一个列没有索引,涉及的索引都不会被使用到;
  • 发生隐式转换;
  • 使用联合索引时,查询条件未包含联合索引的第一个字段(未准守最左匹配原则);
  • 字符类型查询时不带引号导致索引失效;
  • 不同字段值对比导致索引失效;
    从一张表中查询出一些值,然后根据这些值去其他表中筛选数据,这个业务也是实际项目中较为常见的场景,下面为了简单实现,就简单用姓名和性别模拟一下字段对比的场景:(其中user_name属于联合索引的第一个字段)
EXPLAIN SELECT * FROM `zz_users` WHERE user_name = user_sex;

在这里插入图片描述

  • 反向范围操作导致索引失效
    一般来说,如果SQL属于正向范围查询,例如>、<、between、like、in...等操作时,索引是可以正常生效的,但如果SQL执行的是反向范围操作,例如NOT IN、NOT LIKE、IS NOT NULL、!=、<>...等操作时,就会出现问题,例如:
EXPLAIN SELECT * FROM `zz_users` WHERE user_id NOT IN(1,2,3);

在这里插入图片描述

使用NOT关键字做反向范围查询时,并不会走索引,索引此时失效了,但是做正向范围查询时,索引依旧有效

  • 走索引扫描的行数超过表行数的30%
    在MySQL中还有一种特殊情况会导致索引失效,也就是当走索引扫描的行数超过表行数的30%时,MySQL会默认放弃索引查询,转而使用全表扫描的方式检索数据,因此这种情况下走索引的顺序磁盘IO,反而不一定有全表的随机磁盘IO快。

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

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

相关文章

java面向对象,全是对象,这么多对象2023015

面向对象&#xff08;一遍一遍的领悟&#xff09; Java支持面向对象的三大特征&#xff1a;封装、继承和多态&#xff0c; Java提供 了private、protected和public三个访问控制修饰符来实现良好的封装&#xff0c;提供了extends关键字来让子类继承父类&#xff0c;子类继承父类…

人工智能图像形状检测算法

博主简介 博主是一名大二学生&#xff0c;主攻人工智能研究。感谢让我们在CSDN相遇&#xff0c;博主致力于在这里分享关于人工智能&#xff0c;c&#xff0c;Python&#xff0c;爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主&#xff0c;博主会继续更新的&#xff0c…

Redis下载安装与配置(linux)

一、Redis下载与安装 1.下载安装包 官网下载地址&#xff1a;Download | Redis 点击"Download 7.0.7"&#xff0c;即可进行下载。 2.将安装包上传至服务器 2.1将安装包上传至/usr/local目录并解压 cd /usr/local lstar -zxvf redis-7.0.7.tar.gz2.2删除安装包 r…

第二天总结 之 商品类型管理界面的实现 之 添加和修改操作 的实现

添加和修改操作 页面跳转问题 点击修改按钮时 跳转的路径 如下 点击添加按钮时 跳转的路径如下 通过这两张图片 不难发现 跳转的是同一个jsp 但是添加操作 是不带id跳转 而修改操作是带着id跳转 所以在其 跳转的页面add_goods_type.jsp页面中 有一个这样的判断 如果没有id…

Linux常用命令——tmux命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) tmux Tmux是一个优秀的终端复用软件&#xff0c;类似GNU Screen&#xff0c;但来自于OpenBSD&#xff0c;采用BSD授权。 补充说明 使用它最直观的好处就是&#xff0c;通过一个终端登录远程主机并运行tmux后&a…

2022年HarmonyOS/OpenHarmony生态观察

一、鸿蒙生态世界快速构建升级中 HarmonyOS鸿蒙2019年正式面世&#xff0c;当时消费者只能在华为的智慧屏上体验&#xff1b;2020年&#xff0c;鸿蒙智联-华为面向智能硬件生态伙伴全新品牌和开放平台发布&#xff1b;2021年&#xff0c;智能手机等多种终端全面搭载HarmonyOS2…

UE4 RenderDoc笔记

1.Meh Viewer&#xff1a;当前DrawCall的Mesh信息&#xff0c;可以查看每个点的输入和输出 可以看到该DrawCall的Mesh顶点数量为510&#xff08;该材质ID的Mesh三角面数&#xff09;170*3&#xff0c;第一个顶点ID为3637 2.Texture Viewer:查看该次事件所调用的输入、输出缓…

【进阶】Spring Boot创建和使用

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录一、Spring Boot 概述二、Spring Boot优点三、Spring Boot项目创建1. 使用IDEA创建&#xff08;社区版&#xff09;2. 网页版创建&#xff08;了解&#xff09;四、项目目录介绍和运行1. 项目目录介绍2. 输出hello w…

Win10 Hyper-V 固定虚拟机IP地址的方法

Windows10系统Hyper-V中存在着一个名为“Default Switch”的缺省虚拟交换机&#xff0c;其本质上是一块虚拟网卡&#xff0c;其所连接的虚拟网络的类型为"Internal"&#xff08;有关Hyper-V三种网络类型的含义&#xff0c;可参看《Hyper-V三种虚拟网络类型的理解_bol…

“深度学习”学习日记。误差反向传播法--算法实现

2023.1.18 经过学习了计算图、链式法则、加法层、乘法层、激活函数层、Affine层、Softmax层的反向传播的实现。今天来学习反向传播法的算法实现&#xff0c;做一次总结&#xff1b; 实现的思路&#xff08;“学习”的步骤&#xff09;&#xff1a; 一&#xff0c;前提 神经…

4.Java的基础语法

小伙伴们,本篇内容让我们一起来总结学习Java的基础语法吧!&#x1f609; 文章目录一、注释二、关键字三、字面量(也被叫做:常量/字面值常量)四、一些特殊字面量的书写五、变量(1)变量的定义格式:(2)输出打印变量:(3)变量的基本用法:(4)变量的注意事项:(5)变量的练习总结一、注释…

【第二章 Excel数据格式】

Excel数据格式1.Excel数据格式2.更改单元格格式2.1数值型数据的更改2.2文本型数据的更改2.3日期型数据的更改2.4日期型数据、数值型数据->文本型数据1.Excel数据格式 数字、文本和日期是最常用的三种数据格式&#xff0c; 数字一般右对齐&#xff0c;方便观测数据位数&am…

mac ganache安装以及在metamask创建ganache网络和账户导入

在做区块链本地测试时&#xff0c;需要测试网络、测试账户以及测试币&#xff0c;可以使用ganache来启动本地网络以及生成账户进行测试。 一、下载及安装ganache 首先下载ganache&#xff0c; 网址是这个https://trufflesuite.com/ganache/ 下载好后进行安装。 安装好以后使用…

Allegro如何让BUS线以粗线形式显示操作指导

Allegro如何让BUS线以粗线形式显示操作指导 在评估PCB布线的时候,设置好Bus线对于评估非常有帮助,Allegro不仅可以支持设置Bus组,还可以让Bus线以粗线形式显示,如下图 具体操作如下 选择Edit-PropertyFind选择nets

【algorithm】算法基础课---二分查找算法(附笔记 | 建议收藏)

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;AcWing算法学习笔记 &#x1f4ac;总结&#xff1a;希望你看完…

几种常用的权重初始化方法

来源&#xff1a;投稿 作者&#xff1a;175 编辑&#xff1a;学姐 在深度学习中&#xff0c;权重的初始值非常重要&#xff0c;权重初始化方法甚至关系到模型能否收敛。本文主要介绍两种权重初始化方法。 为什么需要随机初始值 我们知道&#xff0c;神经网络一般在初始化权重…

【EasyExcel】在Java中操作Excel 完成数据的导入导出

快速入门 引入依赖 构建实体类 数据导出 参数 WriteWorkbook WriteSheet WriteTable 测试 数据导入 测试 EasyExcel是阿里巴巴开源的一个excel处理框架&#xff0c;以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一…

【Ajax】form表单

一、form表单的基本使用什么是表单表单在网页中主要负责数据采集功能。HTML中的<form>标签&#xff0c;就是用于采集用户输入的信息&#xff0c;并通过<form>标签的提交操作&#xff0c;把采集到的信息提交到服务器端进行处理。2. 表单的组成部分<!-- 表单标签 …

Android 深入系统完全讲解(27)

讲完了这块&#xff0c;我们来说下相机相关的&#xff0c;再说之前一定记得&#xff0c;先要有框架思维&#xff0c;这点一直是我 强调的。 相机是什么&#xff0c;硬件采集数据上来&#xff0c;解析完成&#xff0c;上层绘制&#xff0c;在绘制的时候&#xff0c;同步可以做特…

iOS 国际化(多语言)

一、应用程序国际化 包括app名称和各种权限的提示文字。 1.1 创建工程&#xff0c;再在“PROJECT”的“Info”里面&#xff0c;添加所需语言。 1.2 从代码中分离出文本 创建一个 “.strings” 扩展名的文件 来本地化字符串&#xff0c;需要把这些字符串全部放在一个单独的文…