MySQL:索引优化、查询优化

article/2025/11/7 6:44:28

一、哪些情况适合创建索引

1、字段的数值有唯一性的限制;

业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引;

说明:创建唯一索引会影响添加的速度(在添加的时候会维护索引),但是这个速度影响可以忽略,但是可以显著的提高查询的速度;

2、频繁作为WHERE查询条件的字段;

3、经常使用GROUP BY 和ORDER BY的列;

说明:在创建索引的时候,B+树中的所有是按照一定顺序排列的,所有在分组和排序的时候会提高查询速度

补充:如果既有GROUP BY又有ORDER BY,建议添加联合索引,联合索引中GROUP BY中的索引在前,ORDER BY的索引在后,因为在查询的时候先查询GROUP BY中的再查询ORDER BY中的;

4、 UPDATE、DELETE的WHERE条件列;

5、DISTINCT字段需要创建索引;

6、多表JOIN连续操作的时候,创建索引注意事项:

首先:连接表的数量不要超过3张,因为每多一个表,就相当于多了一次嵌套循环,是一个数量级的增长,影响查询效率;

其次,对WHERE条件创建索引,因为WHERE才是对数据条件的过滤。如果再数据量非常大的情况下,没有WHERE影响是非常大的;

最后,对于连接的字段创建索引,并且该字段再多张表中的类型必须一致,因为如果类型不一致,可能出现数据类型的隐式转换,这个过程会用到函数,当用到函数的时候,创建的索引就失效了;

7、使用列的类型小的创建索引(能用小的就用小的)

类型小指的是该类型表示的数据范围大小;

数据类型小,再查询的时候操作比较快;

数据类型小,索引所占用的空间也就越少,在一个数据页中也就可以放下更多的记录,B+Tree就会更加矮胖,从而减少磁盘I/O的次数,提高效率;

说明:这个对于主键来说更加适用,因为不仅在聚簇索引中会存储主键,在二级索引的节点处也会存储主键,如果主键使用更小的数据类型,就意味着节省更多的存储空间,就可以在一个数据页中放更多的内容,减少IO次数;

8、使用字符串前缀创建索引;

1、过长的字符串会占用很大的空间,如果用过长的字符串创建索引,就会导致索引中占用的存储空间大;

2、B+树索引中的所有列存储的字符串很长,在做字符串比较的时候就会占用更多的时间;

9、区分度高(散列性高)的列适合作为索引,也就是重复项少;

10、使用最频繁的列放在联合索引的最左侧(遵循最左侧前缀原则)

11、在多个字段都要创建索引的时候,联合索引优于单值索引;

限制索引的数目,建议单张表索引数量不超过6个;

1、每个索引都会占用磁盘空间,索引越多需要的磁盘空间也就越大;

2、索引会影响INSERT DELETE UPDATE等语句的性能,因为表中数据在更改的时候,索引也需要进行维护;

3、优化器在选择如何优化查询的时候,会根据统一信息,对每一个可以用到的所有来进行评估,生成一个好的执行计划,如果同时有很多个索引都可以用于查询,会增加MySQL优化器生成执行计划的时间,降低查询性能;

二、哪些情况不适合创建索引

1、在WHERE中使用不到的字段,不要设置索引;

2、数据量小的表最好不要使用索引;

3、有大量重复数据的列上不要建立索引;

4、避免对经常更新的列创建过多的索引;

5、不建议用无序的值作为索引;(出现页分裂次数频繁)

6、不再使用或者很少使用的索引;

7、不要定义冗余或者重复的索引;

三、索引优化、查询优化

SQL优化大致上可以分为:物理查询优化逻辑查询优化

物理查询优化是通过:索引、表连接方式进行优化;(重点掌握)

逻辑查询优化是通过:SQL等价变换提升查询效率(也就是换一种查询写法执行效率可能更高);

3.1 索引失效

1、最佳左前缀法则

索引文件具有B-Tree的最左前缀匹配特性,如果最左边的值没有确定,就无法使用索引;

2、计算、函数、类型转换(自动或者手动)导致索引失效;

3、范围条件右边的索引失效

ALTER TABLE student ADD INDEX idex_age_classId_name(age,classId,NAME);EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE student.age=30 AND student.`classId` > 20 AND student.`name` = 'abc';
-- classId是一个范围条件,创建索引的时候再name在他的右边,所以namae字段索引失效;
-- 和WHERE中的顺序没有关系
EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE student.age=30 AND student.`name` = 'abc' AND student.`classId` > 20;

 创建联合索引的时候,务必把范围查找的字段设置在最后;

4、不等于(!= 或者<>)索引失效;

5、is null (相当于等于)可以使用索引,is not null不可以使用索引(相当于不等于)

结论:在创建数据表的时候将字段设置为 NOT NULL约束,如果一定要有NULL的需求,可以把默认值设置为0,字符串类型的默认值设置为空字符串’‘。

拓展:在查询中使用 not like也无法使用,会导致全表扫描;

6、like以通配符%开头索引失效(因为B+Tree中不知道你前面是啥,找不到)

强制:页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决;

7、OR前后存在非索引的列,索引失效 (取并集,没有索引的哪一个会进行全表查询)

8、数据库和表的字符不统一;

不同的字符集进行比较的时候需要进行转换会造成索引失效 

3.2 关联查询优化

1、采用左外连接

        左外连接中左边的表全要,所以type是All不需要添加索引,所以需要在被驱动表中添加索引;(右外连接类似)

2、采用内连接、

        两表都没有索引,或者两表都有索引的时候,小表驱动大表(大结果集的作为被驱动表);

        两表中只有一个有索引的时候,有索引的表被作为被驱动表;

 JOIN语句原理

小结:

1、索引嵌套循环连接(Index Nested-Loop Join)(添加索引 ) > Block Nested-Loop Join (运用了Join Buffer)> 简单嵌套循环

2、永远用小结果集驱动大结果集(本质就是减少外层循环的数据数量);

3、为被驱动匹配的条件增加索引(减少内层表的循环匹配次数);

4、增大join buffer size的大小(一次缓存的数据多,内层表的扫表次数就减少);

5、减少不必要的字段查询(字段越少,join buffer缓存的数据也就越多);

MySQL 8.0 的时候用Hash Join取代了Block Nested-Loop Join;

3.3 子查询优化

子查询执行效率不高的原因:

1、在执行子查询的时候,MySQL需要给内层查询语句的查询结果创建一个临时表,然后外层擦汗寻语句,从临时表中查询数据,查询完毕之后再撤销临时表。创建和销毁的过程会消耗过多的CPU和IO资源,产生大量的慢查询;

2、临时表是没有索引的,对于查询性能有一定的影响,特别是数据量很大的时候影响更大

解决方案:使用连接(JOIN)查询来替代子查询,连接查询不需要建立临时表,速度比子查询要快,在查询中使用索引的话,性能会更好;

3.4 排序优化

 问题:在WHERE条件字段上加索引,但是为什么在ORDER BY字段上还要加索引

回答:

在MySQL,支持两种排序方式,分别是FileSort,和Index排序

1、在Index排序中,索引可以保证数据的有序性,不需要再进行排序,效率更高;

2、FileSort排序则一般在内存中进行排序,占用CPU较多。如果待排结果较大,会产生临时文件I/O到磁盘进行排序的情况,效率较低;

优化建议:

1、SQL中,可以在WHERE子句和ORDER BY子句中使用索引,目的是在WHERE子句中避免全表扫描在ORDER BY 子句中避免FileSort排序,当然某些情况下全表扫描,或者FileSort排序不一定比索引慢,但总的来说,我们还是要避免,提高查询效率;

2、尽量使用Index完成ORDER BY排序,说如果WHERE和ORDER BY后面是相同的列就使用单索引列,如果不同就使用联合索引;

3、无法使用Index时,需要对FileSort方式进行调优;

3.5 覆盖索引

        一个索引包含了满足查询结果的数据叫做覆盖索引;

好处:

1、避免Innodb表进行索引的而此查询(回表)

2、可以把随机IO变成顺序IO(因为回表的时候是随机IO的,在索引中排好序了,但是在回表的时候,两个数据可能在不同的数据页 )加快查询效率

四、索引下推

4.1 定义

        索引下推一般运用在联合索引中

        索引下推运用在非聚簇索引中(二级索引),因为索引下推主要就是在回表之前先进行一下判断、过滤,减少回表的次数然后减少随机IO;

         目前存在一个联合索引 zipcode_lastname_pero 

        虽然lastname中有模糊查询并且是%开头的,索引会失效,但是,如果通过成本计算之后,优化器发现,通过索引下推也就是用到了索引lastname之后过滤掉的条件可以减少回表的次数;减少随机IO;

4.2 好处

        ICP可以减少存储引擎必须访问基表的次数和MySQL服务器必须访问存储引擎的次数;

补充:

一、SELECT COUNT(*) 、SELECT COUNT(1) 、SELECT COUNT(具体字段)

1、如果是对所有结果进行COUNT(*)、COUNT(1)是相等的;

2、如果是对行数进行统计:

        2.1 如果是MyISAM存储引擎,统计数据表的行数只需要O(1)的复杂度,因为在MyISAM中有一个信息记录了行数值;

        2.2 如果是InnoDB存储引擎,没有记录行数,所有需要进行全表扫描是O(n)复杂度;

3、在InnoDB中,如果采用COUNT(字段)来统计行数,尽量采用二级索引,因为聚簇索引中包含的信息多,大于二级索引,对于COUNT(*)、COUNT(1)来说不需要去找具体字段,只需要统计行数,所以回去自动选择一个占用空间小的二级索引来进行统计(根据ken_len来进行选择);

二、不建议使用SELECT *的原因

        1、MySQL在解析的时候,会通过查询数据字典,将”*“转换为所有列名,会消耗资源和时间;

        2、无法使用覆盖索引;

三、LIMIT 1对优化的影响

        如果是一个进行全表扫描的SQL语句,如果确定结果集只有一个就可以加上LIMIT 1来加快查询速度;

        如果已经对字段建立了唯一索引(不会重复,找到了之后就不会继续往下找了),这个时候就不需要加上LIMIT;

五、范式

        第一范式:确保每列保持原子性;、

        数据库的每一列都是不可分割的原子数据项,不可再 分的最小数据单元,而不能是集合、数组、记录等非原子数据项;

        第二范式 : 确保每一列都和主键完全依赖,也就是要和主键有关;

        第三范式:确保每列都和主键直接相关,非主键之间不能有关系;

        范式的优点:减少数据冗余;

        范式的缺点:降低查询的效率;(表变多了);


http://chatgpt.dhexx.cn/article/tqm4B0QX.shtml

相关文章

Mysql-索引优化

一、索引基本知识 1、索引的优点 很大程度上减少服务器扫描的数据量很大程度上避免服务器排序和临时表将随机IO变成顺序IO 2、索引的用处 使用索引列可以快速查找Where条件的行数据 mysql> explain select * from emp where empno 7469; ----------------------------…

MySQL索引优化总结

前言&#xff1a;相信大家都知道索引可以大大提高MySQL的检索速度&#xff0c;但是真正在平时工作中写SQL&#xff0c;真的会考虑到这条SQL如何能够用上索引提升执行效率&#xff1f;本篇博客详细的介绍了索引优化的20个原则&#xff0c;只要在工作中能够随时应用到&#xff0c…

【MySQL】深入理解MySQL索引优化器原理(MySQL专栏启动)

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码&#xff0c;就职于大型金融公司后端高级工程师&#xff0c;擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &#x1…

mysql 索引优化

一、mysql索引建立原则 二、通过 EXPLAIN 分析 SQL 执行计划 可以知道以下内容&#xff1a; 假设现在我们使用 EXPLAIN 命令查看当前 SQL 是否使用了索引&#xff0c;先通过 SQL EXPLAIN 导出相应的执行计划如下&#xff1a; 下面对图示中的每一个字段进行一个说明&#x…

【MySQL】MySQL索引优化——从原理分析到实践对比

目录 使用TRACE分析MySQL优化 开启TRACE TRACE 结果集 ORDER BY & GROUP BY 优化 优化方式 分页优化 不同场景的优化方式 JOIN关联优化 算法介绍 优化方式 COUNT优化 优化方式 使用TRACE分析MySQL优化 某些情况下&#xff0c;MySQL是否走索引是不确定的[,,_,,…

MySQL索引常见面试题(2022版)

目录 为什么要建立索引&#xff1f; 哪些情况适合建立索引&#xff1f; 哪些情况下不适合建索引&#xff1f; 为什么索引是使用B树&#xff1f;&#xff08;重点&#xff09; 索引分为那几类&#xff1f; 什么是聚簇索引&#xff1f;&#xff08;重点&#xff09; 使用聚…

mysql数据库索引优化【建议收藏】

在我们程序员玩数据库的时候&#xff0c;经常会写sql&#xff0c;但是决定一个sql的好坏往往是效率&#xff0c;于是我们需要不断的去优化我们的sql&#xff0c;写一句让人称赞的sql是非常不容易的&#xff0c;也是需要大家有非常深厚的功底&#xff0c;所以优化路漫漫&#xf…

MySQL索引优化

MySQL索引优化 一、优化索引的方法二、优化步骤前缀索引优化覆盖索引优化主键索引最好是自增的索引最好设置为NOT NULL防止索引失效 总结 一、优化索引的方法 这里说一下几种常见优化索引的方法&#xff1a; 前缀索引优化&#xff1b; 覆盖索引优化&#xff1b; 主键索引最好是…

Android底层到上层的开发流程

安卓系统整体框架图如下&#xff1a; 简单总结如下&#xff1a; 1、在kernel层编写你的驱动程序&#xff1a;生成设备文件节点跟上一层传输数据&#xff0c;主要调用函数copy_to_user和copy_from_user&#xff0c;注意赋节点权限问题。 2、在HAL层封装对上提供的函数接口&…

【Android】Android底层开发实战

本书分为四个部分&#xff1a;第一部分为预备知识篇&#xff0c;简要介绍嵌入式系统的定义与软硬件开发以及Android开发环境的搭建。第二部分为系统结构篇&#xff0c;主要介绍Android系统的源码结构、内核与相关工具以及环境库。第三部分为驱动设计篇&#xff0c;主要介绍Andr…

我做了几年的Android应用层开发,为什么还要去学习安卓系统知识?

作为一个工作了好几年的Android应用层开发者&#xff0c;我准备在工作之余干一件事情&#xff0c;那就是学习Android系统知识&#xff0c;为什么要做这个决定呢&#xff1f; 其主要原因是想在Android应用层开发进阶 这个说起来并非易事&#xff0c;可能在很多人的认知里&…

一个Android应用层开发如何转型深入Android Framework?

作为一个工作了好几年的Android应用层开发者&#xff0c;准备在工作之余干一件事情&#xff0c;那就是分享一些Android系统知识&#xff0c;为什么决定要做这个呢&#xff0c;理由如下&#xff1a; 帮助更多人转型Android系统开发 不知何时起&#xff0c;单纯的Android应用层…

android底层开发-android基础架构

android architecture 在安卓中&#xff0c;最经典的架构就是分四层&#xff0c;分别是application、framework、libraries、kernel四层&#xff0c;通过这四层将android的整个架构都丰满起来 其架构图如下 android 系统组成 &#xff30;rocess FW: android 系统固件&#…

Android Framework 开发揭解密,移动开发者必须掌握的底层原理

作为过来人&#xff0c;发现很多学习者和实践者都在 Android Framework上面临着很多的困扰&#xff0c;比如&#xff1a; 工作场景中遇到难题&#xff0c;往往只能靠盲猜和感觉&#xff0c;用临时性的补救措施去掩盖&#xff0c;看似解决了问题&#xff0c;但下次同样的问题又会…

Android系统底层架构【译】

Android系统底层架构 转载请注明来源&#xff1a;http://blog.csdn.net/lifeshow 设备移植 Android提供了设备移植和支持方面有较大的自由度&#xff0c;可以制定自有的设备规范和驱动。通过硬件抽象层&#xff08;HAL-Hardware Abstraction Layer&#xff09;&#xff0c;可以…

嵌入式Android底层开发

嵌入式Linux主要有这几部分&#xff1a; Bootloader&#xff1a;主要用于引导Linux内核到内存中&#xff0c;让内核进行自解压并运行 zImage&#xff1a;带自解压的Linux内核 <Board>.dtb&#xff1a;每个型号的主板都有对应的设备树(保存对应的设备型号等信息&#x…

android 底层系统开发,Android底层

概述-Android系统架构 Android系统架构 概述-Application Application Android平台不仅仅是操作系统&#xff0c;同时也包含了许多应用&#xff0c;如桌面&#xff0c;浏览器&#xff0c;视频客户端&#xff0c;摄像头等。用JAVA编写&#xff0c;可以被开发人员开发的其他应用程…

Android 开发之 ---- 底层驱动开发(二)

Android 设备驱动&#xff08;下&#xff09; MTD 驱动 Flash 驱动通常使用 MTD &#xff08;memory technology device )&#xff0c;内存技术设备。 MTD 的字符设备&#xff1a; /dev/mtdX 主设备号 90. MTD 的块设备&#xff1a; /dev/block/mtdblockX 主设备号 13. MTD 驱…

写给Android App开发人员看的Android底层知识(1)

这个系列的文章一共8篇&#xff0c;我酝酿了很多年&#xff0c;参考了很多资源&#xff0c;查看了很多源码&#xff0c;直到今天把它写出来&#xff0c;也是战战兢兢&#xff0c;生怕什么地方写错了&#xff0c;贻笑大方。 &#xff08;一&#xff09;引言 早在我还是Android菜…

读懂底层,才是安卓真正开始的时候

对于android开发&#xff0c;我们大部分工作都是在应用层&#xff0c;但为了体现"技术含量"&#xff0c;以及"知其所以然"&#xff0c;以便在遇到具体问题时不至于束手无策&#xff0c;因此有必要了解底层的工作机制。 比如Android NDK 开发可能在平时的项…